Permalink
Browse files

Add a rotational symmetry finder

Test Plan:
Crossed fingers.

Auditors: eater, cbhl
  • Loading branch information...
1 parent f66560c commit c00fddd219f4f4784804af7416ec3b057a3d6c7b @sophiebits sophiebits committed Apr 4, 2013
Showing with 54 additions and 3 deletions.
  1. +54 −3 utils/geom.js
View
@@ -6,6 +6,7 @@
var sub = function(p1, p2) { return {x: p1.x - p2.x, y: p1.y - p2.y}; };
var len = function(p) { return Math.sqrt(p.x * p.x + p.y * p.y); };
var dist = function(p1, p2) { return len(sub(p1, p2)); };
+ var dot = function(p1, p2) { return p1.x * p2.x + p1.y * p2.y; };
var cross = function(p1, p2) { return p1.x * p2.y - p1.y * p2.x; };
var ccw = function(p1, p2, p3) { return cross(sub(p2, p1), sub(p3, p1)); };
@@ -27,7 +28,7 @@
} else if (b == v0) {
return 1;
}
-
+
var c = ccw(v0, a, b);
if (eq(c, 0)) {
var d1 = dist(v0, a);
@@ -49,15 +50,65 @@
_.each(points, function(p) {
var l = ch.length;
while (ch.length >= 2 &&
- ccw(ch[ch.length - 2], ch[ch.length - 1], p) <= 0) {
+ ccw(ch[ch.length - 2], ch[ch.length - 1], p) <= eps) {
ch.pop();
}
ch.push(p);
});
return ch;
+ },
+
+ /**
+ * Return a list of angles between 0 and 2 pi, in radians, through
+ * which the passed-in set of points have rotational symmetry (about
+ * the origin).
+ */
+ rotationalSymmetries: function(points) {
+ var n = points.length,
+ v0 = points[0],
+ angles = [],
+ twoPi = 2 * Math.PI;
+ console.log(points);
+
+ out: for (var i = 1; i < n; i++) {
+ var v1 = points[i];
+
+ var mag = len(v0) * len(v1);
+ var cos = dot(v0, v1) / mag;
+ var sin = -cross(v0, v1) / mag;
+
+ var rotated = [];
+ for (var j = 0; j < n; j++) {
+ var p = points[(i + j) % n];
+ var rotP = {
+ x: cos * p.x - sin * p.y,
+ y: sin * p.x + cos * p.y
+ };
+
+ if (!eq(dist(rotP, points[j]), 0.0)) {
+ // Points don't line up; no good.
+ console.log(points[j], "!=", rotP);
+ continue out;
+ } else {
+ console.log(points[j], "==", rotP);
+ }
+ }
+
+ var angle = (eps + twoPi + Math.atan2(sin, cos)) % twoPi - eps;
+ if (!eq(angle, 0.0)) {
+ angles.push(angle);
+ }
+ }
+
+ angles = KhanUtil.sortNumbers(angles);
+ angles = _.uniq(angles, /* isSorted: */ true, function() {
+ return KhanUtil.roundToNearest(eps);
+ });
+
+ return angles;
}
}
KhanUtil.Geom = Geom;
-})();
+})();

0 comments on commit c00fddd

Please sign in to comment.