summaryrefslogtreecommitdiff
path: root/scripts/lib/fontbuild/alignpoints.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/lib/fontbuild/alignpoints.py')
-rw-r--r--scripts/lib/fontbuild/alignpoints.py148
1 files changed, 148 insertions, 0 deletions
diff --git a/scripts/lib/fontbuild/alignpoints.py b/scripts/lib/fontbuild/alignpoints.py
new file mode 100644
index 0000000..ed502ed
--- /dev/null
+++ b/scripts/lib/fontbuild/alignpoints.py
@@ -0,0 +1,148 @@
+
+
+import numpy as np
+from numpy.linalg import lstsq
+import math
+
+def alignCorners(glyph, va, subsegments):
+ out = va.copy()
+ # for i,c in enumerate(subsegments):
+ # segmentCount = len(glyph.contours[i].segments) - 1
+ # n = len(c)
+ # for j,s in enumerate(c):
+ # if j < segmentCount:
+ # seg = glyph.contours[i].segments[j]
+ # if seg.type == "line":
+ # subIndex = subsegmentIndex(i,j,subsegments)
+ # out[subIndex] = alignPoints(va[subIndex])
+
+ for i,c in enumerate(subsegments):
+ segmentCount = len(glyph.contours[i].segments)
+ n = len(c)
+ for j,s in enumerate(c):
+ if j < segmentCount - 1:
+ segType = glyph.contours[i].segments[j].type
+ segnextType = glyph.contours[i].segments[j+1].type
+ next = j+1
+ elif j == segmentCount -1 and s[1] > 3:
+ segType = glyph.contours[i].segments[j].type
+ segNextType = "line"
+ next = j+1
+ elif j == segmentCount:
+ segType = "line"
+ segnextType = glyph.contours[i].segments[1].type
+ if glyph.name == "J":
+ print s[1]
+ print segnextType
+ next = 1
+ else:
+ break
+ if segType == "line" and segnextType == "line":
+ subIndex = subsegmentIndex(i,j,subsegments)
+ pts = va[subIndex]
+ ptsnext = va[subsegmentIndex(i,next,subsegments)]
+ # out[subIndex[-1]] = (out[subIndex[-1]] - 500) * 3 + 500 #findCorner(pts, ptsnext)
+ # print subIndex[-1], subIndex, subsegmentIndex(i,next,subsegments)
+ try:
+ out[subIndex[-1]] = findCorner(pts, ptsnext)
+ except:
+ pass
+ # print glyph.name, "Can't find corner: parallel lines"
+ return out
+
+
+def subsegmentIndex(contourIndex, segmentIndex, subsegments):
+ # This whole thing is so dumb. Need a better data model for subsegments
+
+ contourOffset = 0
+ for i,c in enumerate(subsegments):
+ if i == contourIndex:
+ break
+ contourOffset += c[-1][0]
+ n = subsegments[contourIndex][-1][0]
+ # print contourIndex, contourOffset, n
+ startIndex = subsegments[contourIndex][segmentIndex-1][0]
+ segmentCount = subsegments[contourIndex][segmentIndex][1]
+ endIndex = (startIndex + segmentCount + 1) % (n)
+
+ indices = np.array([(startIndex + i) % (n) + contourOffset for i in range(segmentCount + 1)])
+ return indices
+
+def alignPoints(pts, start=None, end=None):
+ if start == None or end == None:
+ start, end = fitLine(pts)
+ out = pts.copy()
+ for i,p in enumerate(pts):
+ out[i] = nearestPoint(start, end, p)
+ return out
+
+def findCorner(pp, nn):
+ if len(pp) < 4 or len(nn) < 4:
+ assert 0, "line too short to fit"
+ pStart,pEnd = fitLine(pp)
+ nStart,nEnd = fitLine(nn)
+ prev = pEnd - pStart
+ next = nEnd - nStart
+ # print int(np.arctan2(prev[1],prev[0]) / math.pi * 180),
+ # print int(np.arctan2(next[1],next[0]) / math.pi * 180)
+ # if lines are parallel, return simple average of end and start points
+ if np.dot(prev / np.linalg.norm(prev),
+ next / np.linalg.norm(next)) > .999999:
+ # print "parallel lines", np.arctan2(prev[1],prev[0]), np.arctan2(next[1],next[0])
+ # print prev, next
+ assert 0, "parallel lines"
+ return lineIntersect(pStart, pEnd, nStart, nEnd)
+
+def lineIntersect((x1,y1),(x2,y2),(x3,y3),(x4,y4)):
+ x12 = x1 - x2
+ x34 = x3 - x4
+ y12 = y1 - y2
+ y34 = y3 - y4
+
+ det = x12 * y34 - y12 * x34
+ if det == 0:
+ print "parallel!"
+
+ a = x1 * y2 - y1 * x2
+ b = x3 * y4 - y3 * x4
+
+ x = (a * x34 - b * x12) / det
+ y = (a * y34 - b * y12) / det
+
+ return (x,y)
+
+def fitLineLSQ(pts):
+ "returns a line fit with least squares. Fails for vertical lines"
+ n = len(pts)
+ a = np.ones((n,2))
+ for i in range(n):
+ a[i,0] = pts[i,0]
+ line = lstsq(a,pts[:,1])[0]
+ return line
+
+def fitLine(pts):
+ """returns a start vector and direction vector
+ Assumes points segments that already form a somewhat smooth line
+ """
+ n = len(pts)
+ if n < 1:
+ return (0,0),(0,0)
+ a = np.zeros((n-1,2))
+ for i in range(n-1):
+ v = pts[i] - pts[i+1]
+ a[i] = v / np.linalg.norm(v)
+ direction = np.mean(a[1:-1], axis=0)
+ start = np.mean(pts[1:-1], axis=0)
+ return start, start+direction
+
+def nearestPoint(a,b,c):
+ "nearest point to point c on line a_b"
+ magnitude = np.linalg.norm(b-a)
+ if magnitude == 0:
+ raise Exception, "Line segment cannot be 0 length"
+ return (b-a) * np.dot((c-a) / magnitude, (b-a) / magnitude) + a
+
+# pts = np.array([[1,1],[2,2],[3,3],[4,4]])
+# pts2 = np.array([[1,0],[2,0],[3,0],[4,0]])
+# print alignPoints(pts2, start = pts[0], end = pts[0]+pts[0])
+# # print findCorner(pts,pts2) \ No newline at end of file