def xispline(pts, ams, eps=0.05, angle_on_straigth=True): """ Calcola i punti base di una linea spline con spigoli che approssima i punti passati in pts, inserendo un punto spigolo quando l'angolo tra due segmenti è maggiore di ams, fino a raggiungere precisione eps. Restituisce la lista dei punti e base e una lista con gli indici relativi ai punti spigolo. """ # Semplifica la linea in input (questo toglie anche i punti doppi) pts = geo2d.simplify(pts, eps/2) # Calcola gli indici dei punti spigolo interni sp = geo2d.getAnglePointsIndexes(pts, ams, angle_on_straigth) # Calcola il risultato finale res = [pts[0]] fsp = [] for i in xrange(0, len(sp)-1): s = geo2d.ispline(geo2d.Path(pts[sp[i]:sp[i+1]+1])) res.extend(s[1:]) fsp.append(len(res)-1) # Salva l'indice (in res!!) del punto spigolo del fsp[-1] # Elimina l'ultimo indice di spigolo auto_closed = geo2d.same(res[0], res[-1]) # Se il primo e l'ultimo punto sono uguali, cancello l'ultimo if auto_closed: del res[-1] fsp.insert(0,0) # In questo caso l'inizio e' sempre punto spigolo return res, fsp, auto_closed
def testReversed(self): tprev = self.tp.reversed() expected = [P(0, 2), P(0, 1), P(0, 0)] for p in expected: self.assert_(geo2d.same(p, tprev.path(expected.index(p)))) self.assertAlmostEqual(tprev.t0, 0.8) self.assertAlmostEqual(tprev.t1, 1.5)
def offset(pts, d, tipo="SPIGOLO_VIVO", soglia_unibili=1.0): # Semplifica la linea in input (questo toglie anche i punti doppi) pts = geo2d.simplify(pts, soglia_unibili/50.0) if max(abs(dd) for dd in d) < soglia_unibili*0.6: # Caso speciale per offset a distanza piccolissima: # calcola il risultato considerando semplicemente lo # spostamento punto a punto lungo la bisettrice delle # normali dei segmenti incidenti. La distanza usata # viene modificata per evitare di "tagliare le curve". # Il risultato finale e' una parallela a "spigolo vivo" # corretta a meno delle auto-intersezioni e/o saltelli. # In realtà esiste un caso in cui a questo punto ci sono ancora # dei punti doppi consecutivi, ovvero quello in cui siamo # rimasti con due punti coincidenti. In questo caso non è # chiaro cosa sia l'offset, per cui torniamo il path di partenza # come fa anche la offset di geo2dcpp if len(pts) < 3 and geo2d.same(pts[0], pts[1]): return [geo2d.Path(pts)] chiusa = abs(pts[0] - pts[-1]) < 0.0001 res = [] pts = geo2d.Path(pts) # Gli utilizzatori attuali della offset si aspettano che le curve # chiuse vengano sempre espanse verso l'esterno con offset positivo # e verso l'interno con offset negativo; ora, il lato scelto dalla # funzione offset dipende dal verso della curva, ma visto che non # vogliamo modificarlo solo per mantenere questa invariante, per # ottenere lo stesso risultato inverte il segno dell'offset richiesto. s = 1.0 if chiusa and geo2d.sarea(pts) > 0: s = -1.0 for dd in d: dd *= s off = [] for i in xrange(0, len(pts)): ddir = geo2d.nd(pts, i, dd, chiusa) off.append(pts[i] + ddir) res.append(geo2d.Path(off)) else: tipi = dict(SPIGOLO_VIVO=0, SMUSSATA=1) res = geo2d.offsetf(pts, d, tipi[tipo], soglia_unibili) return res
def assertGeo2dSame(self, p1, p2, prec=1e-3): self.assertTrue(geo2d.same(p1, p2, prec), "%r != %r" % (p1, p2))
def assertGeo2dNotSame(self, p1, p2, prec=1e-6): self.assertFalse(geo2d.same(p1, p2, prec), "%r == %r" % (p1, p2))
def testPt(self): self.assert_(geo2d.same(self.tp.p0, P(0, 0.5))) self.assert_(geo2d.same(self.tp.p1, P(0, 1.2)))