fill function sometimes working and sometimes not working, why?
14 ビュー (過去 30 日間)
古いコメントを表示
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 件のコメント
採用された回答
Star Strider
2025 年 8 月 10 日
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 件のコメント
Star Strider
2025 年 8 月 22 日
@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.
その他の回答 (1 件)
John D'Errico
2025 年 8 月 10 日
編集済み: John D'Errico
2025 年 8 月 10 日
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 件のコメント
John D'Errico
2025 年 8 月 10 日
編集済み: John D'Errico
2025 年 8 月 10 日
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.
参考
カテゴリ
Help Center および File Exchange で Graphics Object Programming についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!