fill function sometimes working and sometimes not working, why?
14 views (last 30 days)
Show older comments
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.
0 Comments
Accepted Answer
Star Strider
on 10 Aug 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]))
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]))
% 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]
directions = mean(diff(xf1_yf1,[],2),2)
fill([xf1, r(2)], [0 yf1], lcol)
xf2=linspace(r(2), r(3), m);
yf2=f(xf2);
xf2_yf2 = [xf2; yf2]
directions = mean(diff(xf2_yf2,[],2),2)
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]
directions = mean(diff(xf1r_yf1r,[],2),2)
fill([xf1r, r(1)], [yf1r, 0], lcol)
xf2=linspace(r(2), r(3), m);
yf2=f(xf2);
xf2_yf2 = [xf2; yf2]
directions = mean(diff(xf2_yf2,[],2),2)
% 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]
directions = mean(diff(xf2r_yf2r,[],2),2)
% fill([xf2r, r(3)], [yf2r, 0], rcol)
fill([xf2r, r(3)], [0 yf2r], rcol)
hold off
% ---------------------- END ----------------------
.
10 Comments
Star Strider
on 22 Aug 2025
@Michael --
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.
More Answers (1)
John D'Errico
on 10 Aug 2025
Edited: John D'Errico
on 10 Aug 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 Comments
John D'Errico
on 10 Aug 2025
Edited: John D'Errico
on 10 Aug 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.
See Also
Categories
Find more on Graphics Object Programming in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!