fill function sometimes working and sometimes not working, why?

14 vues (au cours des 30 derniers jours)
Michael
Michael le 9 Août 2025
Commenté : Star Strider le 22 Août 2025
I am using R2024a on a linux system.
I thought that the fill() command will fill-in a closed polygon with a given colour whether the points are in anti-clockwise order or in clockwise order. In the test script attached I have created a cubic x^3+c*x+d which has 3 real roots r(1)<r(2)<r(3) and I wish to fill-in the region above the axis with one colour and the region below the axis in another colour. I have 3 attempts in what is given in the attachment with just the second attempt working. If I change to c=-2.4 and dfac=0.11 then all 3 cases work. For most choices of the parameters all 3 cases give the same graphics.
There are no warnings or messages when fill() does not do anything.
Is there something that needs to be done to ensure that fill() always works? I guess that I can always give both orders of the points but this will mostly seem to be unnecessary.

Réponse acceptée

Star Strider
Star Strider le 10 Août 2025
I generally use patch rather than fill because I understand patch and I have more control over what it does.
I'm not certain what question you're actually asking, however after experimenting a bit, reversing the arguments of the second fill call (putting the 0 first in all of them) works as I assume you want it to in evary plot with both sets of 'c' and 'dfac'. The reason that approach solves this is not obvious to me. It has something to do with how fill implements patch, however I didn't look through the fill code to search for it.
% ----- test_of_fill -----
% first create a cubic as f()
c=-2.4;
dfac=0.11;
% c=-2.4;
% dfac=0.11;
gamma=sqrt(abs(c)/3);
beta=2*gamma^3;
d=dfac*beta;
f =@(x) x.^3+c*x+d;
% get the roots in ascending order as r()
r=sort(roots([1, 0, c, d]))
r = 3×1
-1.5810 0.0657 1.5153
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
c=-5.8;
dfac=0.38;
% c=-2.4;
% dfac=0.11;
gamma=sqrt(abs(c)/3);
beta=2*gamma^3;
d=dfac*beta;
f =@(x) x.^3+c*x+d;
% get the roots in ascending order as r()
r=sort(roots([1, 0, c, d]))
r = 3×1
-2.5682 0.3603 2.2079
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
% set the number of points and the colours
m=200;
lcol=[0, 0, 1];
rcol=[1, 0, 0];
% first attempt to fillin parts above and below the x-axis
% anti-clockwise for the polygons in both cases
figure(10)
clf
hold on
xf1=linspace(r(2), r(1), m);
yf1=f(xf1);
xf1_yf1 = [xf1; yf1]
xf1_yf1 = 2×200
0.3603 0.3456 0.3309 0.3162 0.3014 0.2867 0.2720 0.2573 0.2426 0.2279 0.2132 0.1984 0.1837 0.1690 0.1543 0.1396 0.1249 0.1101 0.0954 0.0807 0.0660 0.0513 0.0366 0.0218 0.0071 -0.0076 -0.0223 -0.0370 -0.0517 -0.0665 -0.0000 0.0799 0.1602 0.2409 0.3220 0.4036 0.4855 0.5677 0.6503 0.7332 0.8164 0.8999 0.9837 1.0676 1.1518 1.2362 1.3208 1.4056 1.4904 1.5755 1.6606 1.7458 1.8310 1.9163 2.0017 2.0870 2.1724 2.2577 2.3430 2.4282
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
directions = mean(diff(xf1_yf1,[],2),2)
directions = 2×1
-0.0147 0.0000
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
fill([xf1, r(2)], [0 yf1], lcol)
xf2=linspace(r(2), r(3), m);
yf2=f(xf2);
xf2_yf2 = [xf2; yf2]
xf2_yf2 = 2×200
0.3603 0.3696 0.3789 0.3882 0.3974 0.4067 0.4160 0.4253 0.4346 0.4439 0.4532 0.4624 0.4717 0.4810 0.4903 0.4996 0.5089 0.5181 0.5274 0.5367 0.5460 0.5553 0.5646 0.5738 0.5831 0.5924 0.6017 0.6110 0.6203 0.6296 -0.0000 -0.0501 -0.1001 -0.1498 -0.1994 -0.2487 -0.2979 -0.3468 -0.3955 -0.4440 -0.4922 -0.5402 -0.5880 -0.6355 -0.6828 -0.7298 -0.7766 -0.8231 -0.8693 -0.9153 -0.9610 -1.0064 -1.0515 -1.0963 -1.1408 -1.1851 -1.2290 -1.2726 -1.3159 -1.3589
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
directions = mean(diff(xf2_yf2,[],2),2)
directions = 2×1
0.0093 0.0000
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
fill([xf2, r(2)], [0 yf2], rcol)
hold off
% second attempt to fillin parts above and below the x-axis
% clockwise for the left part and anti-clockwise for the right part
figure(20)
clf
hold on
xf1r=linspace(r(1), r(2), m);
yf1r=f(xf1r);
xf1r_yf1r = [xf1r; yf1r]
xf1r_yf1r = 2×200
-2.5682 -2.5535 -2.5387 -2.5240 -2.5093 -2.4946 -2.4799 -2.4652 -2.4504 -2.4357 -2.4210 -2.4063 -2.3916 -2.3769 -2.3621 -2.3474 -2.3327 -2.3180 -2.3033 -2.2886 -2.2739 -2.2591 -2.2444 -2.2297 -2.2150 -2.2003 -2.1856 -2.1708 -2.1561 -2.1414 0.0000 0.2042 0.4050 0.6025 0.7968 0.9878 1.1756 1.3601 1.5415 1.7196 1.8946 2.0664 2.2352 2.4008 2.5633 2.7227 2.8791 3.0325 3.1829 3.3302 3.4746 3.6161 3.7546 3.8901 4.0228 4.1526 4.2796 4.4037 4.5250 4.6435
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
directions = mean(diff(xf1r_yf1r,[],2),2)
directions = 2×1
0.0147 -0.0000
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
fill([xf1r, r(1)], [yf1r, 0], lcol)
xf2=linspace(r(2), r(3), m);
yf2=f(xf2);
xf2_yf2 = [xf2; yf2]
xf2_yf2 = 2×200
0.3603 0.3696 0.3789 0.3882 0.3974 0.4067 0.4160 0.4253 0.4346 0.4439 0.4532 0.4624 0.4717 0.4810 0.4903 0.4996 0.5089 0.5181 0.5274 0.5367 0.5460 0.5553 0.5646 0.5738 0.5831 0.5924 0.6017 0.6110 0.6203 0.6296 -0.0000 -0.0501 -0.1001 -0.1498 -0.1994 -0.2487 -0.2979 -0.3468 -0.3955 -0.4440 -0.4922 -0.5402 -0.5880 -0.6355 -0.6828 -0.7298 -0.7766 -0.8231 -0.8693 -0.9153 -0.9610 -1.0064 -1.0515 -1.0963 -1.1408 -1.1851 -1.2290 -1.2726 -1.3159 -1.3589
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
directions = mean(diff(xf2_yf2,[],2),2)
directions = 2×1
0.0093 0.0000
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
% fill([xf2, r(2)], [yf2, 0], rcol)
fill([xf2, r(2)], [0 yf2], rcol)
hold off
% third attempt to fillin parts above and below the x-axis
% clockwise for the polygons in both cases
figure(30)
clf
hold on
% xf1r=linspace(r(1), r(2), m);
% yf1r=f(xf1r);
fill([xf1r, r(1)], [yf1r, 0], lcol)
xf2r=linspace(r(3), r(2), m);
yf2r=f(xf2r);
xf2r_yf2r = [xf2r; yf2r]
xf2r_yf2r = 2×200
2.2079 2.1986 2.1893 2.1800 2.1707 2.1614 2.1522 2.1429 2.1336 2.1243 2.1150 2.1057 2.0965 2.0872 2.0779 2.0686 2.0593 2.0500 2.0407 2.0315 2.0222 2.0129 2.0036 1.9943 1.9850 1.9758 1.9665 1.9572 1.9479 1.9386 0.0000 -0.0814 -0.1616 -0.2407 -0.3186 -0.3954 -0.4712 -0.5458 -0.6193 -0.6916 -0.7629 -0.8331 -0.9023 -0.9703 -1.0372 -1.1031 -1.1679 -1.2316 -1.2943 -1.3559 -1.4165 -1.4760 -1.5345 -1.5920 -1.6484 -1.7038 -1.7581 -1.8115 -1.8638 -1.9151
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
directions = mean(diff(xf2r_yf2r,[],2),2)
directions = 2×1
-0.0093 -0.0000
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
% fill([xf2r, r(3)], [yf2r, 0], rcol)
fill([xf2r, r(3)], [0 yf2r], rcol)
hold off
% ---------------------- END ----------------------
.
  10 commentaires
Michael
Michael le 22 Août 2025
Below is the response that I have been sent today from mathworks.
"I have investigated about the issue, and this seems like a bug from MATLAB R2022a and the development team is aware of it.''
The original posting was due to not knowing something why something that I was doing several year ago no longer worked in all cases of the parameters. What has been learned is to take care with the use of the fill function if you attempt to close the polygon to fill. It is important to ensure that the last point given is exactly the same as the first point given. If it is different but extremely close then in some cases fill will not do anything and there will not be any warnings.
Star Strider
Star Strider le 22 Août 2025
Thank you for posting the reply. Your best option iw likely to use patch instead, at least until that bug is fixed. In 2D, patch is relatively strtaightforward to work with. The advantage is that it interprets the last point from the available arguments, and completes the region to be filled on its own.

Connectez-vous pour commenter.

Plus de réponses (1)

John D'Errico
John D'Errico le 10 Août 2025
Modifié(e) : John D'Errico le 10 Août 2025
Seems trivial to me. (Ok, easy. Triviality is in the eye of the beholder.) I don't give a hoot about how many real roots it has, or their locations.
fcd = @(x,c,d) x.^3 + c*x + d;
f = @(x) fcd(x,-2.4,0.11);
fplot(f,'k-',[-2,2])
grid on
x = [-2,linspace(-2,2,1000),2];
ypos = max(f(x),0);
ypos([1,end]) = 0;
yneg = min(f(x),0);
yneg([1,end]) = 0;
hold on
fill(x,ypos,'g')
fill(x,yneg,'r')
I never looked at your code, but from what you said, I'll conjecture you were trying too hard, worrying about things like root locations, etc. Sometimes you need to just step back and gain a better focus on the problem.
  3 commentaires
John D'Errico
John D'Errico le 10 Août 2025
Modifié(e) : John D'Errico le 10 Août 2025
What can I say? I showed how to solve your problem, without even needing to worry about the roots. It works nicely, in a very few lines of code. But if this was a homework assignment, well, it is your issue to deal with. You never did tell us the parameters of the assignment, and why you wanted to solve it that way. Honestly, solving for the roots is a poor approach, in the sense that it forces you to do much more work. But an assignment typically dictates how you should solve it. You will get better help if you are forthcoming with what is needed.
Michael
Michael le 10 Août 2025
Thank you again for your contribution and I apologies that my specification may have been too brief. I tried to follow the guidelines in submitting a question which indicated that it should be kept brief.
For a bit more context, it was small part of an assignment that I set for about 100 students several years ago. Every student had a slightly different version of each task and there was about 6 weeks to complete the assignment. Each student was sent a pdf which was 20 pages long which had their version of all the tasks. There was no generic version of the assignment. To get marks students had to do things in the manner asked. Students could work together on similar things but they needed their submission to be for their version of what they are asked to do. This helped cut down on any investigations of collusion that might otherwise arise if everyone is given the same task. As well as generating 100 individual assignments I generated solutions to every different case and this helped when I marked. On revisiting what was done a few years ago I was surprised that an aspect of the ``graphics task'' was not working now in the same way as it did a few years ago. This is what prompted me to submit the question and I could not see why in some cases the fill-in part was not working. I could always get a way to do the task but has taken a while to determine why certain ways might not work. The investigation now has revealed something which might not always work as I wanted.
Just for information, there were other parts of the assignment connected with the graphics task which did not need fill. The most difficult part was in implementing an algorithm that I gave them to attempt to determine and show the largest circle that you can put in the filled region with the larger area.
I still have an old computer with release R20a. On that computer the fill function works as it did a few years ago. All the fill instructions did what I wanted. With release R24a and also the online version R25a I get a small number of cases where the programs from few year ago no longer work as they did before. It seems that the implementation of the fill function has changed since the assignment was set several years ago.
Thank you for the comment ``Sometimes you need to just step back and gain a better focus on the problem.''
The aspect of that which has helped here is to take care with how you attempt to close a polygon before using the fill function. The default way fill closes a polygon may be the best thing to rely on.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Graphics Object Programming dans Help Center et File Exchange

Produits


Version

R2024a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by