-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reflect method extended for all lines. #2896
Conversation
Perhaps this could be a |
@smichr Reflected entity is possible but many a times we get an ellipse whose axes are not parallel to x and y axes so it is not possible to represent such an ellipse in the standard ellipse object form. |
The above expression is an ellipse which cant be represented in a standard ellipse object form like ,Ellipse(Point(x,y),a,b) |
Yes...until the general ellipse is supported, this should just raise "NotImplementedError". |
@smichr So as most of the reflected entities(Ellipses) are not gonna be a standard ellipse.I think we should implement this as a utility function as you said which returns an equation than raising an error. |
Can you return a Curve instead? |
@smichr Can you return a Curve instead? |
It can be represented in polar form; that could be converted to x-y-coordinate form, couldn't it? http://en.wikipedia.org/wiki/Ellipse#General_parametric_form |
@smichr Yes it can be so should I convert it to polar form? |
@smichr I just checked the polar equation and its even more complicated than the general expression when the center is not at the origin.The general expression looks much better than the polar form. |
I'm just thinking how a GeometricEntity can be returned. So I guess a reflect function that takes an Expr and Line is the next best thing. |
b = a.reflect(line) | ||
p = b.x | ||
q = b.y | ||
a1, a2, a3 = (p.coeff(sin(t)), p.coeff(cos(t)), p.as_independent(sin(t), cos(t))[0]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if a3
is an additive constant then you should use as_independent(sin(t), cos(t), as_Add=True)[0]
@smichr I have also been thinking on those lines but an expression looks like a better solution . |
@smichr I've added the changes. |
@@ -539,12 +540,26 @@ def reflect(self, line): | |||
>>> from sympy import Circle, Line | |||
>>> Circle((0, 1), 1).reflect(Line((0, 0), (1, 1))) | |||
Circle(Point(1, 0), -1) | |||
>>> Ellipse(Point(3,4),1,3).reflect(Line(Point(0,-4),Point(5,0))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
space after commas
And add a note indicating that until the general Ellipse is supported, an Expr is returned for the Ellipse with a non-horizontal axis.
And there must be something wrong with the calculation:
>>> e1,e2=solve(eq,y)
>>> eq
(-40*x/41 + 9*y/41 + 364/41)**2/9 + (27*x/41 + 120*y/41 + 111/41)**2/9
>>> e1
-320*x/1609 - 41*sqrt(-(41*x - 347)**2)/4827 - 1844/1609
e1 will always be imaginary (which means there is no value of x that will have a corresponding real value of y...so the answer must have gone wrong somewhere.
@smichr I made some changes in the last commit. I added a -1 term .So that would solve this problem I guess |
@@ -539,12 +540,32 @@ def reflect(self, line): | |||
>>> from sympy import Circle, Line | |||
>>> Circle((0, 1), 1).reflect(Line((0, 0), (1, 1))) | |||
Circle(Point(1, 0), -1) | |||
>>> Ellipse(Point(3,4), 1, 3).reflect(Line(Point(0,-4), Point(5,0))) | |||
((-40*x/41 + 9*y/41 + 364/41)**2/9 + (27*x/41 + 120*y/41 + 111/41)**2/9 - 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the answer should be
1600*(9*x/40 + y + 37/40)**2/1681 + 1600*(x - 9*y/40 - 91/10)**2/15129 - 1
You can confirm by plotting the equations (in implicit form) at desmos.com/calculator. I used the equation I derived and posted at SO (referenced in issue #2815)
>>> ge
-1 + (-s*(x - xc) + y - yc)**2/(m**2*(s**2 + 1)) + (s*(y - yc) + x - xc)**2/(M**2*(s**2 + 1))
>>> e=Ellipse((3,4),1,3)
>>> line = Line(Point(0,-4), Point(5,0))
>>> ge.subs(zip((xc,yc), e.center.reflect(line).args)).subs(s,
... Line(e.center,slope=0 if (e.hradius==e.major) else oo).reflect(line).slope
... ).subs(m,e.minor).subs(M,e.major)
1600*(9*x/40 + y + 37/40)**2/1681 + 1600*(x - 9*y/40 - 91/10)**2/15129 - 1
@smichr Our solutions are deferring a bit.I'll explain what I did: |
@@ -424,4 +424,4 @@ def centroid(*args): | |||
A += a | |||
den = A | |||
c /= den | |||
return c.func(*[i.simplify() for i in c.args]) | |||
return c.func(*[i.simplify() for i in c.args]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
newline needed after end of this line
What do you mean "you eliminated cos(t) and sin(t)"; is your answer consistent with
And how are you deriving the final equations? |
Solving both the equations (p q) for sin(t) and cos(t) and squared them and added them which results to one. |
@smichr I got equations following the above procedure. |
@smichr I'll explain it in little more detail. Now squaring and adding equations 1 and 2 will give the result which I obtained.(and replacing p and q with x and y respectively) |
denominator = (a1*b2 - a2*b1)**2 | ||
numerator = (y*a1 - x*b1 + a3*b1 - b3*a1)**2 + (y*a2 - x*b2 + a3*b2 - b3*a2)**2 | ||
result = (numerator/denominator - 1) | ||
raise NotImplementedError('General Ellipse is not supported', result) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
('General Ellipse is not supported but the equation of the reflected Ellipse is:\n', result)
@smichr |
p = b.x | ||
q = b.y | ||
x, y = [_uniquely_named_symbol(name, p) for name in 'xy'] | ||
a1, a2, a3 = (p.coeff(sin(t)), p.coeff(cos(t)), p.as_independent(sin(t), cos(t), as_Add=True)[0]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is coeff even necessary given the simplicity of the arbitrary point?
>>> var('a:d t');Ellipse((a,b),c,d).arbitrary_point(t)
(a, b, c, d, t)
Point(a + c*cos(t), b + d*sin(t))
a1,a2,a3 = 0,self.hradius,self.center.x
b1,b2,b3 = self.vradius,0,self.center.y
@smichr No I'm not applying coeff to the arbitrary point but to the new point which is the result of reflecting the arbitrary point through the given line.So depending on the line coeff is necessary I would say. |
Sorry about that. After posting I thought I might have made that mistake but couldn't get back to correct it until now. Consider the following, though, to see what I mean about fragility:
|
@smichr Thank you for pointing out.It fails in the cases like above.So then i'll use your method and commit? |
I made a checklist at the top of this page. Please just check off the items as you are done and then I will know this is ready to look at again. It's close! |
if line.slope in (0, oo): | ||
c = self.center | ||
c = c.reflect(line) | ||
return self.func(c, -self.hradius, self.vradius) | ||
raise NotImplementedError('reflection line not horizontal | vertical.') | ||
else: | ||
a = self.arbitrary_point() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delete these 3 lines (a, b, p)
@smichr I have made the changes. |
@smichr Duplicate symbols are only being checked for the Ellipse's equation but what about the given line .What if it contains some duplicate symbols? |
""" | ||
def _uniquely_named_symbol(xname, expr): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's change expr -> syms
@smichr But how will the above change remove the line's duplicate symbols? |
delete these 3 lines (a, b, p) |
raise NotImplementedError('reflection line not horizontal | vertical.') | ||
else: | ||
expr = self.equation() | ||
x, y = [_uniquely_named_symbol(name, expr) for name in 'xy'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good catch regarding line
-- how about the changes above with the following?
expr -> `expr.free_symbols.union(line.free_symbols)`
Or we could pass the expressions like _uniquely_named_symbol(name, expr, line)
and then have def _uniquely_named_symbol(xname, *exprs)
and do ... for s in set.union(*[e.free_symbols for e in exprs])
@smichr expr -> |
@smichr Ellipse(Point(3, 4), 1, 3).reflect(Line(Point(0, -4), Point(5, 0))) |
@smichr
|
I'll open a new branch with a few corrections in which I get
|
See #2911 |
str(result)
to"%s == 0" % str(result)