I also didn't try very hard, but it may be difficult to do this. To make geometry return a symbolic result, it has to be completely convinced that a Point is contained in another geometry object. I tried intersecting an arbitrary ellipse with and arbitrary ray, and I got:
Undecidable: Cannot determine if Point(x + (x - z)*(sqrt(-((e**2*(x - z)**2 + hr**2*(t - y)**2)*(-e**2*hr**2 + e**2*(x - x1)**2 + hr**2*(y - y1)**2) - (e**2*(x - x1)*(x - z) - hr**2*(t - y)*(y - y1))**2)/(e**4*hr**4)) - (x - x1)*(x - z)/hr**2 + (t - y)*(y - y1)/e**2)/((x - z)**2/hr**2 + (t - y)**2/e**2), y - (t - y)*(sqrt(-((e**2*(x - z)**2 + hr**2*(t - y)**2)*(-e**2*hr**2 + e**2*(x - x1)**2 + hr**2*(y - y1)**2) - (e**2*(x - x1)*(x - z) - hr**2*(t - y)*(y - y1))**2)/(e**4*hr**4)) - (x - x1)*(x - z)/hr**2 + (t - y)*(y - y1)/e**2)/((x - z)**2/hr**2 + (t - y)**2/e**2)) is in Ray(Point(x, y), Point(z, t)) which is not too surprising, since as you note, not all rays intersect all ellipses. But it might be hard to convince the geometry module using the assumptions that they do. Or it may work. It depends on what conditions you know ahead of time. It would be nice if instead of raising Undecidable, it created some kind of symbolic Intersection object, which then becomes evaluated if symbols are replaced with numbers, and also knows how to numerically compute itself efficiently given floating point values (so that it would be useable with something like lambdify). Aaron Meurer On Tue, Feb 5, 2013 at 6:02 PM, Ronan Lamy <ronan.l...@gmail.com> wrote: > Le 05/02/2013 19:54, Ahmed Kachkach a écrit : > >> Hi ! >> >> For a robotics simulation, I need to calculate the distance that an >> ultrasound sensor would measure (=> distance to the closest obstacle). >> >> Here's the code I'm using to do so (knowing that what's in "self.shapes" >> has been parsed from an SVG file and is mainly ellipses): >> >> def RayDistance(self, x, y, headingAngle): >> >> ray = Ray(Point(x,y), angle=headingAngle) >> >> minDist = None >> >> for shape in self.shapes: >> >> intersections = ray.intersection(shape) >> >> for intersection in intersections: >> >> distance = intersection.distance(ray.source) >> >> print "Shape {} ; Intersection {} ; Distance {}".format(shape, >> intersection, distance) >> >> if minDist == None: >> >> minDist = distance >> >> elif distance < minDist: >> >> minDist = distance >> >> return minDist >> >> >> Doing this is extremely slow, even with just 3 shapes. If I go up to 200 >> shapes, I only get about 1 frame per second. And I only detectect a >> collision from time to time (especially if I slightly change my heading >> angle while facing a same obstacle). >> >> For instance, I'm using Qt for the visualisation and my "headingAngle" >> is in radians and ccw (0 being horizantal, headed to the positive x), my >> coordinates are floats and using the graphical reference system (=> >> positive Xs to the "right" and positive Ys to the bottom) >> >> It's my first experience with Sympy, so I may just be using the wrong >> tools for what I'm trying to do. > > > Well, whenever you try to call sympy functions with floating point arguments > repeatedly, you are doing it wrong. In this case, you should not call sympy > functions at runtime. Instead, you should use symbolic computations to > derive the relevant formulas, convert them to numpy functions, and use only > numpy at runtime. Schematically, it would look like: > > import sympy as sy > import numpy as np > > x, y, angle, a, b, c = sy.symbols("x, y, theta, a, b, c", real=True) > > def make_ellipse(param_a, param_b, param_c): > """Convert ellipse params to Ellipse object""" > ... > > # Derive the formula > ray = sy.Ray(sy.Point(x, y), angle=angle) > ellipse = make_ellipse(a, b, c) > intersection = ray.intersection(ellipse) > closest_point = intersection[0] # a bit of wishful thinking here... > distance = closest_point.distance(ray.source) > > # Make a numerical function > n_distance = sy.lambdify([x, y, angle, a, b, c], distance, "numpy") > > # assuming self.params is a n-by-3 numpy array of ellipse parameters > def ray_distance(self, x, y, angle): > return np.min(n_distance(x, y, angle, self.params[:, 0], > self.params[:, 1], self.params[:, 2])) > > Now, I haven't tested this, and I have completely ignored the fact that not > all ellipses intersect the ray, but I hope that you get the idea. If you can > put your calculations in this form, it should be orders magnitudes faster > than your first attempt. > > Ronan > > > > -- > You received this message because you are subscribed to the Google Groups > "sympy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to sympy+unsubscr...@googlegroups.com. > To post to this group, send email to sympy@googlegroups.com. > Visit this group at http://groups.google.com/group/sympy?hl=en. > For more options, visit https://groups.google.com/groups/opt_out. > > -- You received this message because you are subscribed to the Google Groups "sympy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sympy+unsubscr...@googlegroups.com. To post to this group, send email to sympy@googlegroups.com. Visit this group at http://groups.google.com/group/sympy?hl=en. For more options, visit https://groups.google.com/groups/opt_out.