11# Geometry Library - Reusable classes for geometric operations
22
33from functools import cache
4- import bisect
54
65
76class Line :
@@ -97,38 +96,23 @@ def inter(self, ray):
9796class Polygon :
9897 """Represents a polygon defined by its vertices"""
9998
100- def __init__ (self , vertices , precision = 2 , epsilon = 1e-3 ):
99+ def __init__ (self , vertices , epsilon = 1e-3 ):
101100 """
102101 Initialize a polygon with vertices.
103102
104103 Args:
105- vertices: List of (x, y) tuples (can be floats)
106- precision: Number of decimal digits (e.g., 2 for 0.01 precision)
107- Coordinates are scaled by 10^precision to work with integers
104+ vertices: List of (x, y) tuples
108105 epsilon: tolerance for floating point comparisons in Line operations
109106 """
110- self .precision = precision
111- self .multiplier = 10 ** precision
112107 self .epsilon = epsilon
113108
114- # Extract unique x and y coordinates, sort them, and create mappings
115- xs = sorted (set (x for x , y in vertices ))
116- ys = sorted (set (y for x , y in vertices ))
117-
118- # Store mappings for converting back to original coordinates
119- self .xs = xs
120- self .ys = ys
121-
122- # Convert vertices to indices (scaled integer coordinates)
123- indexedVertices = [(xs .index (x ), ys .index (y )) for x , y in vertices ]
124-
125- # Build edges as rays using indexed coordinates
109+ # Build edges as rays from vertices
126110 self .edges = []
127- n = len (indexedVertices )
111+ n = len (vertices )
128112
129113 for i in range (n ):
130- x1 , y1 = indexedVertices [i ]
131- x2 , y2 = indexedVertices [(i + 1 ) % n ]
114+ x1 , y1 = vertices [i ]
115+ x2 , y2 = vertices [(i + 1 ) % n ]
132116
133117 line = Line ((x1 , y1 ), (x2 , y2 ), epsilon = self .epsilon )
134118
@@ -152,86 +136,29 @@ def condition(p, X1=x1, X2=x2, Y1=y1, Y2=y2):
152136
153137 self .edges .append (Ray (line , condition ))
154138
155- def addCoords (self , coords ):
156- """
157- Pre-add a list of coordinates to the mappings.
158- Useful to add many coordinates at once efficiently.
159-
160- Args:
161- coords: List of (x, y) tuples to add to the coordinate mappings
162- """
163- # Extract all unique x and y values from coords
164- newXs = set (x for x , y in coords )
165- newYs = set (y for x , y in coords )
166-
167- # Merge and sort if there are new coordinates
168- xsChanged = False
169- ysChanged = False
170-
171- for x in newXs :
172- if x not in self .xs :
173- xsChanged = True
174- break
175-
176- for y in newYs :
177- if y not in self .ys :
178- ysChanged = True
179- break
180-
181- if xsChanged :
182- self .xs = sorted (set (self .xs ) | newXs )
183- if ysChanged :
184- self .ys = sorted (set (self .ys ) | newYs )
185-
186- def _toIndexed (self , p ):
187- """
188- Convert a point in original coordinates to indexed coordinates.
189- If the coordinate doesn't exist, it's inserted in sorted order.
190-
191- Args:
192- p: (x, y) tuple in original coordinate system
193-
194- Returns:
195- (xIdx, yIdx) tuple in indexed coordinate system
196- """
197- xOrig , yOrig = p
198-
199- # Find or insert x coordinate using binary search
200- xIdx = bisect .bisect_left (self .xs , xOrig )
201- if xIdx >= len (self .xs ) or self .xs [xIdx ] != xOrig :
202- self .xs .insert (xIdx , xOrig )
203-
204- # Find or insert y coordinate using binary search
205- yIdx = bisect .bisect_left (self .ys , yOrig )
206- if yIdx >= len (self .ys ) or self .ys [yIdx ] != yOrig :
207- self .ys .insert (yIdx , yOrig )
208-
209- return (xIdx , yIdx )
210-
211139 @cache
212140 def inside (self , p ):
213141 """
214142 Check if point p is inside the polygon using ray casting algorithm.
215143
216144 Args:
217- p: (x, y) tuple in original coordinate system
145+ p: (x, y) tuple
218146
219147 Returns:
220148 True if point is inside polygon, False otherwise
221149 """
222- # Convert original coordinates to indexed coordinates
223- x , y = self ._toIndexed (p )
150+ x , y = p
224151
225152 # Cast rays in four cardinal directions from the point
226153 # A point is inside if all four rays intersect at least one edge
227154 rays = [
228- Ray (Line (( x , y ) , (x - 10 , y ), epsilon = self .epsilon ),
155+ Ray (Line (p , (x - 10 , y ), epsilon = self .epsilon ),
229156 lambda p1 , X = x : p1 [0 ] <= X ), # Left
230- Ray (Line (( x , y ) , (x , y + 10 ), epsilon = self .epsilon ),
157+ Ray (Line (p , (x , y + 10 ), epsilon = self .epsilon ),
231158 lambda p1 , Y = y : p1 [1 ] >= Y ), # Up
232- Ray (Line (( x , y ) , (x + 10 , y ), epsilon = self .epsilon ),
159+ Ray (Line (p , (x + 10 , y ), epsilon = self .epsilon ),
233160 lambda p1 , X = x : p1 [0 ] >= X ), # Right
234- Ray (Line (( x , y ) , (x , y - 10 ), epsilon = self .epsilon ),
161+ Ray (Line (p , (x , y - 10 ), epsilon = self .epsilon ),
235162 lambda p1 , Y = y : p1 [1 ] <= Y ) # Down
236163 ]
237164
0 commit comments