Skip to content

Commit fe3fb68

Browse files
committed
Added bezier to experimental since it was not tested yet.
1 parent ff0d555 commit fe3fb68

1 file changed

Lines changed: 185 additions & 0 deletions

File tree

gem/experimental/bezier.py

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
import math
2+
from gem import vector
3+
import six.moves as sm
4+
5+
6+
# Cubic Bezier Cruve
7+
def cubicBezierPoint(t, p0, p1, p2, p3):
8+
u = 1 - t
9+
tt = t * t
10+
uu = u * u
11+
uuu = uu * u
12+
ttt = tt * t
13+
14+
p = uuu * p0
15+
p += 3 * uu * t * p1
16+
p += 3 * u * tt * p2
17+
p += ttt + p3
18+
19+
return p
20+
21+
# Quadratic Bezier Curve
22+
def quadraticBezierPoint(t, p0, p1, p2):
23+
u = 1 - t
24+
tt = t * t
25+
uu = u * u
26+
27+
p = uu * p0
28+
p += 2 * u * t * p1
29+
p += tt * p2
30+
31+
return p
32+
33+
class BezierPath(object):
34+
def __init__(self):
35+
self.segments_per_curve = 10
36+
self.minimum_sqr_distance = 0.01
37+
self.divison_threshold = -0.99
38+
39+
self.controlPoints = []
40+
self.curveCount = 0
41+
42+
def setControlPoints(self, newControlPoints):
43+
self.controlPoints = newControlPoints
44+
self.curveCount = (len(self.controlPoints) - 1) / 3
45+
46+
def getControlPoints(self):
47+
return self.controlPoints
48+
49+
def interpolate(self, segmentPoints, scale):
50+
51+
segmentPointsLen = len(segmentPoints)
52+
53+
if segmentPointsLen < 2:
54+
return
55+
56+
for i in sm.range(segmentPointsLen):
57+
if i == 0:
58+
p1 = segmentPoints[i]
59+
p2 = segmentPoints[i + 1]
60+
61+
tangent = p2 - p1
62+
q1 = p1 + scale * tangent
63+
64+
self.controlPoints.append(p1)
65+
self.controlPoints.append(q1)
66+
elif i == segmentPointsLen - 1:
67+
p0 = segmentPoints[i - 1]
68+
p1 = segmentPoints[i]
69+
70+
tangent = p1 - p0
71+
q0 = p1 - scale * tangent
72+
73+
self.controlPoints.append(q0)
74+
self.controlPoints.append(p1)
75+
else:
76+
p0 = segmentPoints[i - 1]
77+
p1 = segmentPoints[i]
78+
p2 = segmentPoints[i + 1]
79+
tangent = (p2 - p0).normalize()
80+
q0 = p1 - scale * tangent * (p1 - p0).magnitude()
81+
q1 = p1 + scale * tangent * (p2 - p1).magnitude()
82+
83+
self.controlPoints.append(q0)
84+
self.controlPoints.append(p1)
85+
self.controlPoints.append(q1)
86+
87+
self.curveCount = (len(self.controlPoints) - 1) / 3
88+
89+
def samplePoints(self, sourcePoints, minSqrDistance, maxSqrDistance, scale):
90+
sourcePointsLen = len(sourcePoints)
91+
92+
if (sourcePointsLen < 2):
93+
return
94+
95+
samplePoints = []
96+
97+
samplePoints.append(sourcePoints[0])
98+
99+
potentialSamplePoint = sourcePoints[1]
100+
101+
for i in sm.range(2, sourcePointsLen, 1):
102+
# These variables need better names
103+
pointDiff = potentialSamplePoint - sourcePoints[i]
104+
pointDIff2 = samplePoints[len(samplePoints) - 2] - sourcePoints[i]
105+
106+
if (pointDiff.sqrMagnitude() > minSqrDistance and
107+
pointDIff2.sqrMagnitude() > maxSqrDistance):
108+
samplePoints.append(potentialSamplePoint)
109+
potentialSamplePoint = sourcePoints[i]
110+
111+
p1 = samplePoints[len(samplePoints) - 1]
112+
p0 = samplePoints[len(samplePoints) - 2]
113+
tangent = (p0 - potentialSamplePoint).normalize()
114+
d2 = (potentialSamplePoint - p1).magnitude()
115+
d1 = (p1 - p0).magnitude()
116+
p1 = p1 + tangent * ((d1 - d2) / 2)
117+
118+
samplePoints.append(p1)
119+
samplePoints.append(potentialSamplePoint)
120+
121+
self.interpolate(samplePoints, scale)
122+
123+
def calculateBezerPoint(self, curveIndex, t):
124+
nodeIndex = curveIndex * 3
125+
126+
p0 = self.controlPoints[nodeIndex]
127+
p1 = self.controlPoints[nodeIndex + 1]
128+
p2 = self.controlPoints[nodeIndex + 2]
129+
p3 = self.controlPoints[nodeIndex + 3]
130+
131+
return cubicBezierPoint(t, p0, p1, p2, p3)
132+
133+
# Find the drawing points of the curve using recusive divison
134+
# Less points but same accuracy
135+
def getDrawingPoints(self):
136+
drawingPoints = []
137+
138+
for i in sm.range(self.curveCount):
139+
bezierCurveDrawingPoints = self.findDrawingPoints(i)
140+
141+
if i != 0:
142+
del bezierCurveDrawingPoints[0]
143+
144+
drawingPoints.append(bezierCurveDrawingPoints)
145+
146+
return drawingPoints
147+
148+
def findDrawingPoints(self, curveIndex):
149+
pointList = []
150+
151+
left = self.calculateBezerPoint(curveIndex, 0)
152+
right = self.calculateBezerPoint(curveIndex, 1)
153+
154+
pointList.append(left)
155+
pointList.append(right)
156+
157+
self.findDrawingPointsAdded(curveIndex, 0, 1, pointList, 1)
158+
159+
return pointList
160+
161+
def findDrawingPointsAdded(self, curveIndex, t0, t1, pointList, insertionIndex):
162+
left = self.calculateBezerPoint(curveIndex, t0)
163+
right = self.calculateBezerPoint(curveIndex, t1)
164+
165+
if (left - right).sqrMagnitude() < self.minimum_sqr_distance:
166+
return 0
167+
168+
tMid = (t0 - t1) / 2
169+
mid = self.calculateBezerPoint(curveIndex, tMid)
170+
171+
leftDirection = (left - mid).normalize()
172+
rightDirection = (right - mid).normalize()
173+
174+
if (leftDirection.dot(rightDirection) > self.divison_threshold or
175+
math.abs(tMid - 0.5) < 0.0001):
176+
pointsAddedCount = 0
177+
178+
pointsAddedCount += self.findDrawingPointsAdded(curveIndex, t0, tMid, pointList, insertionIndex)
179+
pointList.append(insertionIndex + pointsAddedCount, mid)
180+
pointsAddedCount += 1
181+
pointsAddedCount += self.findDrawingPointsAdded(curveIndex, tMid, t1, pointList, insertionIndex + pointsAddedCount)
182+
183+
return pointsAddedCount
184+
185+
return 0

0 commit comments

Comments
 (0)