diff --git a/src/corners.py b/src/corners.py new file mode 100644 --- /dev/null +++ b/src/corners.py @@ -0,0 +1,97 @@ +from epoint import * + + +class Corners: + def __init__(self): + self.corners=[] + + def add(self,x,y): + a=EPoint(x,y) + # for i,c in enumerate(self.corners): # move an improperly placed point + # if a.dist(c)<20: + # self.corners[i]=a + # return + + if len(self.corners)<4: # add a new corner + self.corners.append(a) + + if len(self.corners)<4: + return + + index,minDist=0,float('inf') # replace the corner closest to the clicked point + for i,c in enumerate(self.corners): + if a.dist(c) KLMN | ABC | ABD | ACD | BCD | index | swap + # ------------ | :-: | :-: | :-: | :-: | ----: | ---- + # A BCD | + | + | + | + | 15 | 0 + # A BDC | + | + | - | - | 12 | CD + # A CBD | - | + | + | - | 6 | BC + # A CDB | - | - | + | + | 3 | AB + # A DBC | + | - | - | + | 9 | AD + # A DCB | - | - | - | - | 0 | BD + # + # For every non-degenerate quadrangle, there must be 1-3 edges going right-left (from a higher to a lower x coordinate). + # From these pick the one with the lowest slope (dy/dx) and declare its ending point the upper left corner. For the same slope pick the one further left. + # + # @return True for a convex quadrangle, False for concave or degenerate cases. + def _canonizeOrder(self): + if len(self.corners)!=4: return False # erroneus call + + a,b,c,d=(x for x in self.corners) + abc=Corners._doubleTriangleArea(a,b,c) + abd=Corners._doubleTriangleArea(a,b,d) + acd=Corners._doubleTriangleArea(a,c,d) + bcd=Corners._doubleTriangleArea(b,c,d) + + if any(x==0 for x in (abc,abd,acd,bcd)): return False # collinear degenerate + + swaps=[(1,3),(0,1),(1,2),(0,3),(2,3),(0,0)] + index=(8 if abc>0 else 0)+(4 if abd>0 else 0)+(2 if acd>0 else 0)+(1 if bcd>0 else 0) + if index%3!=0: return False # concave degenerate + swap=swaps[index//3] + + self.corners[swap[0]], self.corners[swap[1]] = self.corners[swap[1]], self.corners[swap[0]] # counter-clockwise order + + kIndex=None + lowestSlope=float("inf") + + for i,corner in enumerate(self.corners): # find the NK edge: going right-left with the lowest slope, secondarily the one going down + ii=(i+1)%4 + slope=abs(Corners._slope(corner,self.corners[ii])) + if corner.x>self.corners[ii].x and (slope