def is_collinear(*points): """Is a sequence of points collinear? Test whether or not a set of points are collinear. Returns True if the set of points are collinear, or False otherwise. Parameters ---------- points : sequence of Point Returns ------- is_collinear : boolean Notes -------------------------- Slope is preserved everywhere on a line, so the slope between any two points on the line should be the same. Take the first two points, p1 and p2, and create a translated point v1 with p1 as the origin. Now for every other point we create a translated point, vi with p1 also as the origin. Note that these translations preserve slope since everything is consistently translated to a new origin of p1. Since slope is preserved then we have the following equality: v1_slope = vi_slope => v1.y/v1.x = vi.y/vi.x (due to translation) => v1.y*vi.x = vi.y*v1.x => v1.y*vi.x - vi.y*v1.x = 0 (*) Hence, if we have a vi such that the equality in (*) is False then the points are not collinear. We do this test for every point in the list, and if all pass then they are collinear. Examples -------- >>> from sympy import Point >>> from sympy.abc import x >>> p1, p2 = Point(0, 0), Point(1, 1) >>> p3, p4, p5 = Point(2, 2), Point(x, x), Point(1, 2) >>> Point.is_collinear(p1, p2, p3, p4) True >>> Point.is_collinear(p1, p2, p3, p5) False """ points = GeometryEntity.extract_entities(points) if len(points) == 0: return False if len(points) <= 2: return True # two points always form a line # XXX Cross product is used now, but that only extends to three # dimensions. If the concept needs to extend to greater # dimensions then another method would have to be used p1 = points[0] p2 = points[1] v1 = p2 - p1 for p3 in points[2:]: v2 = p3 - p1 test = simplify(v1[0]*v2[1] - v1[1]*v2[0]) if simplify(test) != 0: return False return True
def is_concurrent(*lines): """ Returns True if the set of linear entities are concurrent, False otherwise. Two or more linear entities are concurrent if they all intersect at a single point. Description of Method Used: =========================== Simply take the first two lines and find their intersection. If there is no intersection, then the first two lines were parallel and had no intersection so concurrency is impossible amongst the whole set. Otherwise, check to see if the intersection point of the first two lines is a member on the rest of the lines. If so, the lines are concurrent. """ _lines = lines lines = GeometryEntity.extract_entities(lines) # Concurrency requires intersection at a single point; One linear # entity cannot be concurrent. if len(lines) <= 1: return False try: # Get the intersection (if parallel) p = GeometryEntity.do_intersection(lines[0], lines[1]) if len(p) == 0: return False # Make sure the intersection is on every linear entity for line in lines[2:]: if p[0] not in line: return False return True except AttributeError: return False
def intersection(*entities): """The intersection of a collection of GeometryEntity instances. Parameters ---------- entities : sequence of GeometryEntity Returns ------- intersection : list of GeometryEntity Raises ------ NotImplementedError When unable to calculate intersection. Notes ----- The intersection of any geometrical entity with itself should return a list with one item: the entity in question. An intersection requires two or more entities. If only a single entity is given then the function will return an empty list. It is possible for `intersection` to miss intersections that one knows exists because the required quantities were not fully simplified internally. Reals should be converted to Rationals, e.g. Rational(str(real_num)) or else failures due to floating point issues may result. Examples -------- >>> from sympy.geometry import Point, Line, Circle, intersection >>> p1, p2, p3 = Point(0, 0), Point(1, 1), Point(-1, 5) >>> l1, l2 = Line(p1, p2), Line(p3, p2) >>> c = Circle(p2, 1) >>> intersection(l1, p2) [Point(1, 1)] >>> intersection(l1, l2) [Point(1, 1)] >>> intersection(c, p2) [] >>> intersection(c, Point(1, 0)) [Point(1, 0)] >>> intersection(c, l2) [Point(1 - 5**(1/2)/5, 1 + 2*5**(1/2)/5), Point(1 + 5**(1/2)/5, 1 - 2*5**(1/2)/5)] """ from entity import GeometryEntity entities = GeometryEntity.extract_entities(entities, False) if len(entities) <= 1: return [] res = GeometryEntity.do_intersection(entities[0], entities[1]) for entity in entities[2:]: newres = [] for x in res: newres.extend(GeometryEntity.do_intersection(x, entity)) res = newres return res
def is_concurrent(*lines): """Is a sequence of linear entities concurrent? Two or more linear entities are concurrent if they all intersect at a single point. Parameters ---------- lines : a sequence of linear entities. Returns ------- True if the set of linear entities are concurrent, False otherwise. Notes ----- Simply take the first two lines and find their intersection. If there is no intersection, then the first two lines were parallel and had no intersection so concurrency is impossible amongst the whole set. Otherwise, check to see if the intersection point of the first two lines is a member on the rest of the lines. If so, the lines are concurrent. Examples -------- >>> from sympy import Point, Line >>> p1, p2 = Point(0, 0), Point(3, 5) >>> p3, p4 = Point(-2, -2), Point(0, 2) >>> l1, l2, l3 = Line(p1, p2), Line(p1, p3), Line(p1, p4) >>> l1.is_concurrent(l2, l3) True >>> l4 = Line(p2, p3) >>> l4.is_concurrent(l2, l3) False """ _lines = lines lines = GeometryEntity.extract_entities(lines) # Concurrency requires intersection at a single point; One linear # entity cannot be concurrent. if len(lines) <= 1: return False try: # Get the intersection (if parallel) p = GeometryEntity.do_intersection(lines[0], lines[1]) if len(p) == 0: return False # Make sure the intersection is on every linear entity for line in lines[2:]: if p[0] not in line: return False return True except AttributeError: return False
def __new__(cls, *args, **kwargs): vertices = GeometryEntity.extract_entities(args, remove_duplicates=False) if len(vertices) != 3: raise GeometryError("Triangle.__new__ requires three points") for p in vertices: if not isinstance(p, Point): raise GeometryError("Triangle.__new__ requires three points") return GeometryEntity.__new__(cls, *vertices, **kwargs)
def is_concyclic(*points): """Is a sequence of points concyclic? Test whether or not a sequence of points are concyclic (i.e., they lie on a circle). Parameters ---------- points : sequence of Points Returns ------- is_concyclic : boolean True if points are concyclic, False otherwise. Notes ----- No points are not considered to be concyclic. One or two points are definitely concyclic and three points are conyclic iff they are not collinear. For more than three points, create a circle from the first three points. If the circle cannot be created (i.e., they are collinear) then all of the points cannot be concyclic. If the circle is created successfully then simply check the remaining points for containment in the circle. Examples -------- >>> from sympy.geometry import Point >>> p1, p2 = Point(-1, 0), Point(1, 0) >>> p3, p4 = Point(0, 1), Point(-1, 2) >>> Point.is_concyclic(p1, p2, p3) True >>> Point.is_concyclic(p1, p2, p3, p4) False """ points = GeometryEntity.extract_entities(points) if len(points) == 0: return False if len(points) <= 2: return True if len(points) == 3: return not Point.is_collinear(*points) try: from ellipse import Circle c = Circle(points[0], points[1], points[2]) for point in points[3:]: if point not in c: return False return True except GeometryError, e: # Circle could not be created, because of collinearity of the # three points passed in, hence they are not concyclic. return False
def intersection(*entities): """ Finds the intersection between a list GeometryEntity instances. Returns a list of all the intersections, Will raise a NotImplementedError exception if unable to calculate the intersection. Examples: ========= >>> from sympy.geometry import * >>> p1,p2,p3 = Point(0,0), Point(1,1), Point(-1, 5) >>> l1, l2 = Line(p1, p2), Line(p3, p2) >>> c = Circle(p2, 1) >>> intersection(l1, p2) [Point(1, 1)] >>> intersection(l1, l2) [Point(1, 1)] >>> intersection(c, p2) [] >>> intersection(c, Point(1, 0)) [Point(1, 0)] >>> intersection(c, l2) [Point(1 - 1/5*5**(1/2), 1 + 2*5**(1/2)/5), Point(1 + 1/5*5**(1/2), 1 - 2*5**(1/2)/5)] Notes: ====== - The intersection of any geometrical entity with itself should return a list with one item: the entity in question. - An intersection requires two or more entities. If only a single entity is given then one will receive an empty intersection list. - It is possible for intersection() to miss intersections that one knows exists because the required quantities were not fully simplified internally. """ from entity import GeometryEntity entities = GeometryEntity.extract_entities(entities, False) if len(entities) <= 1: return [] res = GeometryEntity.do_intersection(entities[0], entities[1]) for entity in entities[2:]: newres = [] for x in res: newres.extend( GeometryEntity.do_intersection(x, entity) ) res = newres return res
def intersection(*entities): """ Finds the intersection between a list GeometryEntity instances. Returns a list of all the intersections, Will raise a NotImplementedError exception if unable to calculate the intersection. Examples: ========= >>> from sympy.geometry import * >>> p1,p2,p3 = Point(0,0), Point(1,1), Point(-1, 5) >>> l1, l2 = Line(p1, p2), Line(p3, p2) >>> c = Circle(p2, 1) >>> intersection(l1, p2) [Point(1, 1)] >>> intersection(l1, l2) [Point(1, 1)] >>> intersection(c, p2) [] >>> intersection(c, Point(1, 0)) [Point(1, 0)] >>> intersection(c, l2) [Point(1 - 5**(1/2)/5, 1 + 2*5**(1/2)/5), Point(1 + 5**(1/2)/5, 1 - 2*5**(1/2)/5)] Notes: ====== - The intersection of any geometrical entity with itself should return a list with one item: the entity in question. - An intersection requires two or more entities. If only a single entity is given then one will receive an empty intersection list. - It is possible for intersection() to miss intersections that one knows exists because the required quantities were not fully simplified internally. """ from entity import GeometryEntity entities = GeometryEntity.extract_entities(entities, False) if len(entities) <= 1: return [] res = GeometryEntity.do_intersection(entities[0], entities[1]) for entity in entities[2:]: newres = [] for x in res: newres.extend( GeometryEntity.do_intersection(x, entity) ) res = newres return res
def is_concyclic(*points): """ Test whether or not a set of points are concyclic (i.e., on the same circle). Returns True if they are concyclic, or False otherwise. Example: ======== >>> from sympy.geometry import Point >>> p1,p2 = Point(-1, 0), Point(1, 0) >>> p3,p4 = Point(0, 1), Point(-1, 2) >>> Point.is_concyclic(p1, p2, p3) True >>> Point.is_concyclic(p1, p2, p3, p4) False Description of method used: =========================== No points are not considered to be concyclic. One or two points are definitely concyclic and three points are conyclic iff they are not collinear. For more than three points, we pick the first three points and attempt to create a circle. If the circle cannot be created (i.e., they are collinear) then all of the points cannot be concyclic. If the circle is created successfully then simply check all of the other points for containment in the circle. """ points = GeometryEntity.extract_entities(points) if len(points) == 0: return False if len(points) <= 2: return True if len(points) == 3: return (not Point.is_collinear(*points)) try: from ellipse import Circle c = Circle(points[0], points[1], points[2]) for point in points[3:]: if point not in c: return False return True except GeometryError,e: # Circle could not be created, because of collinearity of the # three points passed in, hence they are not concyclic. return False
def is_concyclic(*points): """ Test whether or not a set of points are concyclic (i.e., on the same circle). Returns True if they are concyclic, or False otherwise. Example: ======== >>> from sympy.geometry import Point >>> p1,p2 = Point(-1, 0), Point(1, 0) >>> p3,p4 = Point(0, 1), Point(-1, 2) >>> Point.is_concyclic(p1, p2, p3) True >>> Point.is_concyclic(p1, p2, p3, p4) False Description of method used: =========================== No points are not considered to be concyclic. One or two points are definitely concyclic and three points are conyclic iff they are not collinear. For more than three points, we pick the first three points and attempt to create a circle. If the circle cannot be created (i.e., they are collinear) then all of the points cannot be concyclic. If the circle is created successfully then simply check all of the other points for containment in the circle. """ points = GeometryEntity.extract_entities(points) if len(points) == 0: return False if len(points) <= 2: return True if len(points) == 3: return (not Point.is_collinear(*points)) try: from ellipse import Circle c = Circle(points[0], points[1], points[2]) for point in points[3:]: if point not in c: return False return True except GeometryError, e: # Circle could not be created, because of collinearity of the # three points passed in, hence they are not concyclic. return False