def projection(self, obj): assert isinstance( obj, baseGeometryObject), 'incorrect object for projection' if isinstance(obj, Line): # TODO: remove 0.0 for future Python 3.X versions tmp = dot(self - obj.basePoint, obj.direction) if isinstance(tmp, oofun): tmp.size = 1 tmp1 = obj.direction * tmp / (0.0 + sum(obj.direction**2)) tmp2 = obj.basePoint if type(tmp1) == ooarray: # hence tmp2 is array tmp2 = tmp2.view(ooarray) return Point(tmp1 + tmp2) elif isinstance(obj, Plane): d1, d2 = obj.directions bp = obj.basePoint a = sum(d1**2) b = d = dot(d1, d2) e = sum(d2**2) c = dot(self - bp, d1) f = dot(self - bp, d2) delta = a * e - b * d + 0.0 # TODO: remove 0.0 when Python 2.x will be deprecated alpha = (c * e - b * f) / delta beta = (a * f - c * d) / delta return Point(bp + alpha * d1 + beta * d2) else: raise SpaceFuncsException( 'not implemented for this geometry object yet')
def projection(self, obj): assert isinstance(obj, baseGeometryObject), 'incorrect object for projection' if isinstance(obj, Line): # TODO: remove 0.0 for future Python 3.X versions tmp = dot(self-obj.basePoint, obj.direction) if isinstance(tmp, oofun): tmp.size = 1 tmp1 = obj.direction*tmp / (0.0+sum(obj.direction**2)) tmp2 = obj.basePoint if type(tmp1) == ooarray: # hence tmp2 is array tmp2 = tmp2.view(ooarray) return Point(tmp1+tmp2) elif isinstance(obj, Plane): d1, d2 = obj.directions bp = obj.basePoint a = sum(d1**2) b = d = dot(d1, d2) e = sum(d2**2) c = dot(self-bp, d1) f = dot(self-bp, d2) delta = a*e-b*d + 0.0 # TODO: remove 0.0 when Python 2.x will be deprecated alpha = (c*e-b*f) / delta beta = (a*f-c*d)/delta return Point(bp + alpha * d1 + beta * d2) else: raise SpaceFuncsException('not implemented for this geometry object yet')
def _centroid(self): tmp = [v.weight is not None for v in self.vertices] if all(tmp): return sum([v*v.weight for v in self.vertices]) / sum([v.weight for v in self.vertices]) elif not any(tmp): return sum(self.vertices)/ float(self.nVertices) else: assert 0, 'to get centroid you should either provide weight for all vertices or for noone'
def skewLinesNearestPoints(line1, line2): assert isinstance(line1, Line) and isinstance(line2, Line) p1, p2 = line1.basePoint, line2.basePoint d1, d2 = line1.direction, line2.direction Delta = sum(d1**2)*sum(d2**2) - dot(d1, d2)**2 Delta1 = dot(d2, p1-p2) * dot(d1, d2) - dot(d1, p1-p2) * sum(d2**2) Delta2 = dot(d2, p1-p2) * sum(d1**2) - dot(d1, d2) * dot(d1, p1-p2) t1 = Delta1 / Delta t2 = Delta2 / Delta for t in [t1, t2]: if isinstance(t, oofun): t.size = 1 return Point(p1+t1*d1), Point(p2+t2*d2)
def skewLinesNearestPoints(line1, line2): assert isinstance(line1, Line) and isinstance(line2, Line) p1, p2 = line1.basePoint, line2.basePoint d1, d2 = line1.direction, line2.direction Delta = sum(d1**2) * sum(d2**2) - dot(d1, d2)**2 Delta1 = dot(d2, p1 - p2) * dot(d1, d2) - dot(d1, p1 - p2) * sum(d2**2) Delta2 = dot(d2, p1 - p2) * sum(d1**2) - dot(d1, d2) * dot(d1, p1 - p2) t1 = Delta1 / Delta t2 = Delta2 / Delta for t in [t1, t2]: if isinstance(t, oofun): t.size = 1 return Point(p1 + t1 * d1), Point(p2 + t2 * d2)
class Polygon(Polytope): _AttributesDict = Polytope._AttributesDict.copy() def __init__(self, *args, **kw): Polytope.__init__(self, *args, **kw) _sides = lambda self: ooarray([sqrt(sum((p1-p2)**2), attachConstraints=False) \ for p1, p2 in \ [(self.vertices[i], self.vertices[i+1]) for i in range(self.nVertices-1)] \ + [(self.vertices[self.nVertices-1], self.vertices[0])]]) _perimeter = lambda self: sum(self.sides) _semiperimeter = lambda self: 0.5 * self.P _angles = lambda self: ooarray([angle(p1, p2) for p1, p2 in \ [(self.vertices[i-1]-self.vertices[i], self.vertices[i+1]-self.vertices[i]) for i in range(self.nVertices-1)]+\ [(self.vertices[self.nVertices-2]-self.vertices[self.nVertices-1], self.vertices[0]-self.vertices[self.nVertices-1])]]) def _area(self): D = self._spaceDimension() if isscalar(D) and D != 2: raise SpaceFuncsException( 'polygon area is not implemented for space dimension > 2 yet') x, y = self._coords(0), self._coords(1) x.append(x[0]) y.append(y[0]) x, y = ooarray(x), ooarray(y) return 0.5 * abs(sum(x[:-1] * y[1:] - x[1:] * y[:-1])) def plot(self, *args, **kw): if not pylabInstalled: raise SpaceFuncsException( 'to plot you should have matplotlib installed') #pylab.Line2D.__init__([self.vertices[i][0] for i in range(3)], [self.vertices[i][1] for i in range(3)]) #raise 0 pylab.plot([ self.vertices[i][0] for i in (arange(self.nVertices).tolist() + [0]) ], [ self.vertices[i][1] for i in (arange(self.nVertices).tolist() + [0]) ], *args, **kw) for i in range(3): self.vertices[i].plot() pylab.draw() __call__ = lambda self, *args, **kw: Polygon( [self.vertices[i](*args, **kw) for i in range(self.nVertices)])
def distance(self, *args, **kw): assert len(kw) == 0 and len(args) == 1 other = args[0] if isinstance(other, (list, tuple)): other = Point(other) if isinstance(other, (Line, Plane)): return self.distance(self.projection(other)) elif isinstance(other, ndarray): return sqrt(sum((self-other)**2), attachConstraints = False)
def _area(self): D = self._spaceDimension() if isscalar(D) and D != 2: raise SpaceFuncsException('polygon area is not implemented for space dimension > 2 yet') x, y = self._coords(0), self._coords(1) x.append(x[0]) y.append(y[0]) x, y = ooarray(x), ooarray(y) return 0.5*abs(sum(x[:-1]*y[1:] - x[1:]*y[:-1]))
def distance(self, *args, **kw): assert len(kw) == 0 and len(args) == 1 other = args[0] if isinstance(other, (list, tuple)): other = Point(other) if isinstance(other, (Line, Plane)): return self.distance(self.projection(other)) elif isinstance(other, ndarray): return sqrt(sum((self - other)**2), attachConstraints=False)
def _area(self): D = self._spaceDimension() if isscalar(D) and D != 2: raise SpaceFuncsException( 'polygon area is not implemented for space dimension > 2 yet') x, y = self._coords(0), self._coords(1) x.append(x[0]) y.append(y[0]) x, y = ooarray(x), ooarray(y) return 0.5 * abs(sum(x[:-1] * y[1:] - x[1:] * y[:-1]))
class Triangle(Polygon): #vertices = None nVertices = 3 _AttributesDict = Polygon._AttributesDict.copy() def __init__(self, *args, **kw): assert len(kw) == 0 and len(args) in (1, 3) Polygon.__init__(self, *args, **kw) __call__ = lambda self, *args, **kw: Triangle( [self.vertices[i](*args, **kw) for i in range(self.nVertices)]) _sides = lambda self: ooarray([sqrt(sum((p1- p2)**2), attachConstraints=False) for p1, p2 in \ ((self.vertices[1], self.vertices[2]), (self.vertices[2], self.vertices[0]), (self.vertices[0], self.vertices[1]))]) _angles = lambda self: ooarray([angle(p1, p2) for p1, p2 in \ ((self.vertices[1]-self.vertices[0], self.vertices[2]-self.vertices[0]), (self.vertices[2]-self.vertices[1], self.vertices[0]-self.vertices[1]), (self.vertices[0]-self.vertices[2], self.vertices[1]-self.vertices[2]))]) _area = lambda self: Polygon._area(self) if self._spaceDimension( ) is 2 else self._areaViaGeron() #_area = lambda self: Polygon._area(self) if self._spaceDimension() is 2 else self._areaViaHeightSideMult() _areaViaGeron = lambda self: sqrt(self.p * (self.p - self.sides[0]) * (self.p - self.sides[1]) * (self.p - self.sides[2]), attachConstraints=False) def _areaViaHeightSideMult(self): proj = self.vertices[0].projection( Line(self.vertices[1], self.vertices[2])) return 0.5 * proj.distance( self.vertices[0]) * self.vertices[1].distance(self.vertices[2]) _circumCircleRadius = lambda self: (self.sides[0] * self.sides[1] * self. sides[2]) / (4 * self.S) _inscribedCircleRadius = lambda self: self.S / self.p _incenter = lambda self: (self.vertices[0] * self.sides[0] + self.vertices[ 1] * self.sides[1] + self.vertices[2] * self.sides[2]) / self.P _orthocenter = lambda self: self.vertices[0].perpendicular(Line(self.vertices[1], self.vertices[2])) \ & self.vertices[1].perpendicular(Line(self.vertices[0], self.vertices[2])) # Eiler's theorem: 2 * vector(OM) = vector(MH) => O = M -0.5 MH = M - 0.5(H-M) = 1.5M - 0.5H _circumCircleCenter = lambda self: 1.5 * self.M - 0.5 * self.H _InscribedCircle = lambda self: Circle(self.I, self.r) _CircumCircle = lambda self: Circle(self.O, self.R)
def _circumSphereCenter(self): a, b, c = self.reducedVertices bc, ca, ab = self.reducedVerticesCrossProduct return (sum(a**2) * bc + sum(b**2) * ca + sum(c**2) * ab) / (2.0*dot(a, bc)) + self.vertices[-1]
def _circumSphereRadius(self): a, b, c = self.reducedVertices bc, ca, ab = self.reducedVerticesCrossProduct return norm(sum(a**2)*bc + sum(b**2)*ca + sum(c**2)*ab) / (12.0 * self.V)