|
|
- // Generated by CoffeeScript 1.6.3
- (function() {
- "use strict";
- var ArcSegment, Board, Chain, Gear, LineSegment, Point, Util,
- __hasProp = {}.hasOwnProperty,
- __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
-
- Point = window.gearsketch.Point;
-
- ArcSegment = window.gearsketch.ArcSegment;
-
- LineSegment = window.gearsketch.LineSegment;
-
- Util = window.gearsketch.Util;
-
- window.gearsketch.model = {};
-
- Gear = (function() {
- function Gear(location, rotation, numberOfTeeth, id, momentum, group, level, connections, hue) {
- this.location = location;
- this.rotation = rotation;
- this.numberOfTeeth = numberOfTeeth;
- this.id = id;
- this.momentum = momentum != null ? momentum : 0;
- this.group = group != null ? group : 0;
- this.level = level != null ? level : 0;
- this.connections = connections != null ? connections : {};
- if (this.id == null) {
- this.id = Util.createUUID();
- }
- this.pitchRadius = Util.MODULE * (0.5 * this.numberOfTeeth);
- this.innerRadius = Util.MODULE * (0.5 * this.numberOfTeeth - 1.25);
- this.outerRadius = Util.MODULE * (0.5 * this.numberOfTeeth + 1);
- this.hue = hue != null? hue : Math.floor(Math.random()*360);
- }
-
- Gear.prototype.getCircumference = function() {
- return 2 * Math.PI * this.pitchRadius;
- };
-
- Gear.prototype.distanceToPoint = function(point) {
- return Math.max(0, this.location.distance(point) - this.pitchRadius);
- };
-
- Gear.prototype.edgeDistance = function(gear) {
- var axisDistance;
- axisDistance = this.location.distance(gear.location);
- return Math.abs(axisDistance - this.pitchRadius - gear.pitchRadius);
- };
-
- Gear.prototype.restore = function(gear) {
- this.location = gear.location;
- this.rotation = gear.rotation;
- this.momentum = gear.momentum;
- this.group = gear.group;
- this.level = gear.level;
- return this.connections = gear.connections;
- };
-
- Gear.prototype.clone = function() {
- return new Gear(this.location.clone(), this.rotation, this.numberOfTeeth, this.id, this.momentum, this.group, this.level, Util.clone(this.connections), this.hue);
- };
-
- Gear.fromObject = function(obj) {
- return new Gear(Point.fromObject(obj.location), obj.rotation, obj.numberOfTeeth, obj.id, obj.momentum, obj.group, obj.level, obj.connections, obj.hue);
- };
-
- return Gear;
-
- })();
-
- window.gearsketch.model.Gear = Gear;
-
- Chain = (function() {
- Chain.WIDTH = 8;
-
- Chain.prototype.points = [];
-
- Chain.prototype.segments = [];
-
- function Chain(stroke, id, group, level, connections) {
- this.id = id;
- this.group = group != null ? group : 0;
- this.level = level != null ? level : 0;
- this.connections = connections != null ? connections : {};
- if (this.id == null) {
- this.id = Util.createUUID();
- }
- this.points = Util.clone(stroke);
- this.rotation = 0;
- }
-
- Chain.prototype.getLength = function() {
- return this.segments.reduce((function(total, segment) {
- return total + segment.getLength();
- }), 0);
- };
-
- Chain.prototype.getCircumference = function() {
- return this.getLength();
- };
-
- Chain.prototype.getStartingPoint = function() {
- if (this.direction === Util.Direction.CLOCKWISE) {
- return this.rotation / (2 * Math.PI) * this.getLength();
- } else {
- return -this.rotation / (2 * Math.PI) * this.getLength();
- }
- };
-
- Chain.prototype.findPointOnChain = function(distance) {
- var distanceToGo, length, segment, segmentLength, _i, _len, _ref;
- length = this.getLength();
- distanceToGo = Util.mod(distance + this.getStartingPoint(), length);
- _ref = this.segments;
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- segment = _ref[_i];
- segmentLength = segment.getLength();
- if (distanceToGo < segmentLength) {
- return segment.findPoint(distanceToGo);
- } else {
- distanceToGo -= segmentLength;
- }
- }
- return null;
- };
-
- Chain.prototype.findPointsOnChain = function(numberOfPoints) {
- var delta, p, _i, _results;
- delta = this.getLength() / numberOfPoints;
- _results = [];
- for (p = _i = 0; 0 <= numberOfPoints ? _i < numberOfPoints : _i > numberOfPoints; p = 0 <= numberOfPoints ? ++_i : --_i) {
- _results.push(this.findPointOnChain(p * delta));
- }
- return _results;
- };
-
- Chain.prototype.distanceToPoint = function(point) {
- var segment;
- return Math.min.apply(null, (function() {
- var _i, _len, _ref, _results;
- _ref = this.segments;
- _results = [];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- segment = _ref[_i];
- _results.push(segment.distanceToPoint(point));
- }
- return _results;
- }).call(this));
- };
-
- Chain.prototype.distanceToSegment = function(s) {
- var segment;
- return Math.min.apply(null, (function() {
- var _i, _len, _ref, _results;
- _ref = this.segments;
- _results = [];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- segment = _ref[_i];
- _results.push(segment.distanceToSegment(s));
- }
- return _results;
- }).call(this));
- };
-
- Chain.prototype.distanceToChain = function(chain) {
- var segment;
- return Math.min.apply(null, (function() {
- var _i, _len, _ref, _results;
- _ref = this.segments;
- _results = [];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- segment = _ref[_i];
- _results.push(chain.distanceToSegment(segment));
- }
- return _results;
- }).call(this));
- };
-
- Chain.prototype.intersectsPath = function(path) {
- var i, j, _i, _ref;
- for (i = _i = 0, _ref = path.length - 1; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- j = i + 1;
- if (this.distanceToSegment(new LineSegment(path[i], path[j])) === 0) {
- return true;
- }
- }
- return false;
- };
-
- Chain.prototype.crossesNonSupportingGears = function(board) {
- var gear, id, _ref;
- _ref = board.getGears();
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- gear = _ref[id];
- if (!(__indexOf.call(this.supportingGearIds, id) >= 0) && !(id in this.ignoredGearIds)) {
- if (this.distanceToPoint(gear.location) < gear.pitchRadius + Util.EPSILON) {
- return true;
- }
- }
- }
- return false;
- };
-
- Chain.prototype.findPointOnSupportingGear = function(gearIndex, incoming) {
- if (incoming) {
- return this.points[Util.mod(2 * gearIndex - 1, this.points.length)];
- } else {
- return this.points[2 * gearIndex];
- }
- };
-
- Chain.prototype.removeGear = function(gear, board) {
- var acknowledgedGears, afterIndex, beforeGear, beforeIndex, g, gears, index, numberOfGears, path, replacementGears;
- while ((index = this.supportingGearIds.indexOf(gear.id)) !== -1) {
- gears = board.getGearsWithIds(this.supportingGearIds);
- numberOfGears = gears.length;
- beforeIndex = Util.mod(index - 1, numberOfGears);
- beforeGear = gears[beforeIndex];
- afterIndex = Util.mod(index + 1, numberOfGears);
- acknowledgedGears = board.getAcknowledgedGears(this.ignoredGearIds);
- path = [this.findPointOnSupportingGear(index, true), this.findPointOnSupportingGear(index, false), this.findPointOnSupportingGear(afterIndex, true)];
- replacementGears = this.findSupportingGearsOnPath(acknowledgedGears, beforeGear, path, 0, false);
- gears.splice.apply(gears, [index, 1].concat(replacementGears));
- this.removeRepeatedGears(gears);
- this.supportingGearIds = (function() {
- var _i, _len, _results;
- _results = [];
- for (_i = 0, _len = gears.length; _i < _len; _i++) {
- g = gears[_i];
- _results.push(g.id);
- }
- return _results;
- })();
- }
- return this.update(board);
- };
-
- Chain.prototype.findChainTangentSide = function(gear) {
- if ((this.direction === Util.Direction.CLOCKWISE) === (gear.id in this.innerGearIds)) {
- return Util.Side.LEFT;
- } else {
- return Util.Side.RIGHT;
- }
- };
-
- Chain.prototype.findReverseChainTangentSide = function(gear) {
- if (this.findChainTangentSide(gear) === Util.Side.LEFT) {
- return Util.Side.RIGHT;
- } else {
- return Util.Side.LEFT;
- }
- };
-
- Chain.prototype.findFirstSupportingGearOnPath = function(path, gears) {
- var a, b, d, pathLength, stepSize, supportingGear;
- stepSize = 10;
- pathLength = Util.getLength(path);
- supportingGear = null;
- a = path[0];
- d = 0;
- while (d < pathLength && (supportingGear == null)) {
- d += stepSize;
- b = Util.findPointOnPath(path, d);
- supportingGear = Util.findNearestIntersectingGear(gears, new LineSegment(a, b));
- }
- return [supportingGear, d];
- };
-
- Chain.prototype.findSupportingGearsOnPath = function(gears, firstSupportingGear, path, startDistance, isClosed) {
- var a, b, d, lineSegment, nextSupportingGear, pathLength, stepSize, supportingGear, supportingGears, tangentPoint, tangentSide;
- if (startDistance == null) {
- startDistance = 0;
- }
- if (isClosed == null) {
- isClosed = true;
- }
- stepSize = 10;
- pathLength = Util.getLength(path, isClosed);
- supportingGear = firstSupportingGear;
- supportingGears = [];
- a = firstSupportingGear.location;
- d = startDistance;
- while (d < pathLength) {
- d += stepSize;
- b = Util.findPointOnPath(path, d);
- tangentSide = this.findReverseChainTangentSide(supportingGear);
- tangentPoint = Util.findGearTangentPoints(b, supportingGear)[tangentSide];
- if (tangentPoint != null) {
- a = tangentPoint;
- }
- lineSegment = new LineSegment(a, b);
- nextSupportingGear = Util.findNearestIntersectingGear(gears, lineSegment, Util.makeSet(supportingGear.id));
- if (nextSupportingGear != null) {
- supportingGear = nextSupportingGear;
- supportingGears.push(supportingGear);
- }
- }
- return supportingGears;
- };
-
- Chain.prototype.removeRepeatedGears = function(gearsList) {
- var g1, g2, i, j, numberOfGears, numberOfNoops;
- numberOfNoops = 0;
- i = 0;
- while (numberOfNoops < (numberOfGears = gearsList.length)) {
- j = (i + 1) % numberOfGears;
- g1 = gearsList[i];
- g2 = gearsList[j];
- if (g1 === g2) {
- gearsList.splice(j, 1);
- numberOfNoops = 0;
- } else {
- numberOfNoops++;
- i = (i + 1) % numberOfGears;
- }
- }
- return gearsList;
- };
-
- Chain.prototype.containsSuccessiveOverlappingGears = function(gearsList) {
- var g1, g2, i, j, numberOfGears, _i;
- numberOfGears = gearsList.length;
- for (i = _i = 0; 0 <= numberOfGears ? _i < numberOfGears : _i > numberOfGears; i = 0 <= numberOfGears ? ++_i : --_i) {
- j = (i + 1) % numberOfGears;
- g1 = gearsList[i];
- g2 = gearsList[j];
- if (g1.location.distance(g2.location) < (g1.outerRadius + g2.outerRadius)) {
- return true;
- }
- }
- return false;
- };
-
- Chain.prototype.findSupportingGearIds = function(gears) {
- var finalSegment, firstSupportingGear, gear, lastSupportingGear, nextSupportingGears, startDistance, supportingGears, tangentPoint, tangentSide, _i, _len, _ref, _ref1, _results;
- _ref = this.findFirstSupportingGearOnPath(this.points, gears), firstSupportingGear = _ref[0], startDistance = _ref[1];
- supportingGears = [firstSupportingGear];
- nextSupportingGears = this.findSupportingGearsOnPath(gears, firstSupportingGear, this.points, startDistance);
- supportingGears = supportingGears.concat(nextSupportingGears);
- tangentSide = this.findChainTangentSide(firstSupportingGear);
- tangentPoint = Util.findGearTangentPoints(this.points[0], firstSupportingGear)[tangentSide];
- if (tangentPoint != null) {
- finalSegment = [this.points[0], tangentPoint];
- lastSupportingGear = supportingGears[supportingGears.length - 1];
- nextSupportingGears = this.findSupportingGearsOnPath(gears, lastSupportingGear, finalSegment, 0, false);
- supportingGears = supportingGears.concat(nextSupportingGears);
- }
- _ref1 = this.removeRepeatedGears(supportingGears);
- _results = [];
- for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
- gear = _ref1[_i];
- _results.push(gear.id);
- }
- return _results;
- };
-
- Chain.prototype.findIgnoredGearIds = function(board) {
- var acknowledgedLevels, currentDistance, currentLevel, d, distance, gear, gears, group, id, ignoredGearIds, level, levels, minDistances, _ref;
- gears = board.getGears();
- minDistances = {};
- for (id in gears) {
- if (!__hasProp.call(gears, id)) continue;
- gear = gears[id];
- group = gear.group;
- level = gear.level;
- d = Util.pointPathDistance(gear.location, this.points) - gear.pitchRadius;
- if ((((_ref = minDistances[group]) != null ? _ref[level] : void 0) == null) || d < minDistances[group][level]) {
- if (minDistances[group] == null) {
- minDistances[group] = {};
- }
- minDistances[group][level] = d;
- }
- }
- acknowledgedLevels = {};
- for (group in minDistances) {
- if (!__hasProp.call(minDistances, group)) continue;
- levels = minDistances[group];
- for (level in levels) {
- if (!__hasProp.call(levels, level)) continue;
- distance = levels[level];
- currentLevel = acknowledgedLevels[group];
- if (currentLevel == null) {
- acknowledgedLevels[group] = parseInt(level, 10);
- } else if (distance > 0) {
- currentDistance = minDistances[group][currentLevel];
- if (currentDistance < 0 || distance < currentDistance) {
- acknowledgedLevels[group] = parseInt(level, 10);
- }
- }
- }
- }
- ignoredGearIds = {};
- for (id in gears) {
- if (!__hasProp.call(gears, id)) continue;
- gear = gears[id];
- if (acknowledgedLevels[gear.group] !== gear.level) {
- ignoredGearIds[id] = true;
- }
- }
- return ignoredGearIds;
- };
-
- Chain.prototype.findIgnoredGearIdsInTightenedChain = function(board) {
- var gear, gearId, group, groups, id, level, updatedIgnoredGearIds, _i, _len, _ref, _ref1;
- groups = {};
- _ref = this.supportingGearIds;
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- gearId = _ref[_i];
- gear = board.getGearWithId(gearId);
- group = gear.group;
- level = gear.level;
- if (groups[group] == null) {
- groups[group] = {};
- }
- groups[group][level] = true;
- }
- updatedIgnoredGearIds = {};
- _ref1 = board.getGears();
- for (id in _ref1) {
- if (!__hasProp.call(_ref1, id)) continue;
- gear = _ref1[id];
- group = gear.group;
- level = gear.level;
- if ((groups[group] != null) && (groups[group][level] == null)) {
- updatedIgnoredGearIds[id] = true;
- }
- }
- return this.ignoredGearIds = updatedIgnoredGearIds;
- };
-
- Chain.prototype.toPolygon = function(segments) {
- var polygon, segment, _i, _len;
- if (segments == null) {
- segments = this.segments;
- }
- polygon = [];
- for (_i = 0, _len = segments.length; _i < _len; _i++) {
- segment = segments[_i];
- if (segment instanceof LineSegment) {
- polygon.push(segment.start);
- } else {
- polygon.push(segment.findPoint(0));
- polygon.push(segment.findPoint(0.5 * segment.getLength()));
- }
- }
- return polygon;
- };
-
- Chain.prototype.update = function(board, gears) {
- var acknowledgedGears, arcEnd, arcSegment, arcStart, chainPolygon, direction, g1, g2, g3, gear, gearId, i, id, intersection, j, k, lineSegment, lineSegment1, lineSegment2, middleSegment, numberOfGears, numberOfSegments, p0, p1, p2, path, replacementGears, s1, s2, tangentLine, tangentPointG1, tangentPointG3, tangentSideG1, tangentSideG3, updatedAcknowledgedGears, updatedIgnoredGearIds, updatedInnerGearIds, updatedPoints, updatedSegments, _i, _j, _k, _l, _ref, _ref1, _ref2;
- if (gears == null) {
- gears = board.getGearsWithIds(this.supportingGearIds);
- }
- if (gears.length < 2) {
- return false;
- }
- if (this.containsSuccessiveOverlappingGears(gears)) {
- return false;
- }
- updatedIgnoredGearIds = this.findIgnoredGearIdsInTightenedChain(board);
- acknowledgedGears = board.getAcknowledgedGears(updatedIgnoredGearIds);
- i = 0;
- while (i < (numberOfGears = gears.length)) {
- j = (i + 1) % numberOfGears;
- k = (i + 2) % numberOfGears;
- g1 = gears[i];
- g2 = gears[j];
- g3 = gears[k];
- lineSegment1 = Util.findTangentLine(g1, g2, this.innerGearIds, this.direction);
- lineSegment2 = Util.findTangentLine(g2, g3, this.innerGearIds, this.direction);
- intersection = lineSegment1.findIntersection(lineSegment2);
- if (intersection != null) {
- tangentSideG1 = this.findReverseChainTangentSide(g1);
- tangentPointG1 = Util.findGearTangentPoints(intersection, g1)[tangentSideG1];
- tangentSideG3 = this.findChainTangentSide(g3);
- tangentPointG3 = Util.findGearTangentPoints(intersection, g3)[tangentSideG3];
- path = [tangentPointG1, intersection, tangentPointG3];
- replacementGears = this.findSupportingGearsOnPath(acknowledgedGears, g1, path, 0, false);
- if (__indexOf.call(replacementGears, g2) >= 0) {
- return false;
- }
- gears.splice.apply(gears, [j, 1].concat(replacementGears));
- this.removeRepeatedGears(gears);
- return this.update(board, gears);
- }
- gear = Util.findNearestIntersectingGear(acknowledgedGears, lineSegment1, Util.makeSet(g1.id, g2.id));
- if (gear != null) {
- gears.splice(j, 0, gear);
- if (this.containsSuccessiveOverlappingGears(gears)) {
- return false;
- }
- }
- i++;
- }
- updatedPoints = [];
- for (i = _i = 0; 0 <= numberOfGears ? _i < numberOfGears : _i > numberOfGears; i = 0 <= numberOfGears ? ++_i : --_i) {
- j = (i + 1) % numberOfGears;
- g1 = gears[i];
- g2 = gears[j];
- tangentLine = Util.findTangentLine(g1, g2, this.innerGearIds, this.direction);
- updatedPoints.push(tangentLine.start, tangentLine.end);
- }
- updatedSegments = [];
- for (i = _j = 0; 0 <= numberOfGears ? _j < numberOfGears : _j > numberOfGears; i = 0 <= numberOfGears ? ++_j : --_j) {
- p0 = updatedPoints[2 * i];
- p1 = updatedPoints[2 * i + 1];
- p2 = updatedPoints[2 * ((i + 1) % numberOfGears)];
- gear = gears[(i + 1) % numberOfGears];
- lineSegment = new LineSegment(p0, p1);
- arcStart = Math.atan2(p1.y - gear.location.y, p1.x - gear.location.x);
- arcEnd = Math.atan2(p2.y - gear.location.y, p2.x - gear.location.x);
- direction = (this.direction === Util.Direction.CLOCKWISE) === (gear.id in this.innerGearIds) ? Util.Direction.CLOCKWISE : Util.Direction.COUNTER_CLOCKWISE;
- arcSegment = new ArcSegment(gear.location, gear.pitchRadius, arcStart, arcEnd, direction);
- updatedSegments.push(lineSegment, arcSegment);
- }
- numberOfSegments = updatedSegments.length;
- for (i = _k = 0, _ref = numberOfSegments - 2; 0 <= _ref ? _k < _ref : _k > _ref; i = 0 <= _ref ? ++_k : --_k) {
- for (j = _l = _ref1 = i + 2; _ref1 <= numberOfSegments ? _l < numberOfSegments : _l > numberOfSegments; j = _ref1 <= numberOfSegments ? ++_l : --_l) {
- if (i !== 0 || j !== numberOfSegments - 1) {
- s1 = updatedSegments[i];
- s2 = updatedSegments[j];
- if (s1.distanceToSegment(s2) < Chain.WIDTH) {
- if ((i + 2) === j) {
- middleSegment = updatedSegments[i + 1];
- if ((middleSegment instanceof ArcSegment) && (middleSegment.getLength() < 2 * Chain.WIDTH)) {
- continue;
- }
- }
- if (((j + 2) % numberOfSegments) === i) {
- middleSegment = updatedSegments[(j + 1) % numberOfSegments];
- if ((middleSegment instanceof ArcSegment) && (middleSegment.getLength() < 2 * Chain.WIDTH)) {
- continue;
- }
- }
- return false;
- }
- }
- }
- }
- updatedIgnoredGearIds = this.findIgnoredGearIdsInTightenedChain(board);
- updatedAcknowledgedGears = board.getAcknowledgedGears(updatedIgnoredGearIds);
- chainPolygon = this.toPolygon(updatedSegments);
- updatedInnerGearIds = {};
- for (id in updatedAcknowledgedGears) {
- if (!__hasProp.call(updatedAcknowledgedGears, id)) continue;
- gear = updatedAcknowledgedGears[id];
- if (Util.isPointInsidePolygon(gear.location, chainPolygon)) {
- updatedInnerGearIds[id] = true;
- }
- }
- _ref2 = this.innerGearIds;
- for (gearId in _ref2) {
- if (!__hasProp.call(_ref2, gearId)) continue;
- if (!(gearId in updatedInnerGearIds) && (__indexOf.call(this.supportingGearIds, gearId) >= 0)) {
- return false;
- }
- }
- this.points = updatedPoints;
- this.segments = updatedSegments;
- this.ignoredGearIds = updatedIgnoredGearIds;
- this.innerGearIds = updatedInnerGearIds;
- this.supportingGearIds = (function() {
- var _len, _m, _results;
- _results = [];
- for (_m = 0, _len = gears.length; _m < _len; _m++) {
- gear = gears[_m];
- _results.push(gear.id);
- }
- return _results;
- })();
- return true;
- };
-
- Chain.prototype.tighten = function(board) {
- var acknowledgedGears, gear;
- this.ignoredGearIds = this.findIgnoredGearIds(board);
- acknowledgedGears = board.getAcknowledgedGears(this.ignoredGearIds);
- this.innerGearIds = Util.makeSetFromList((function() {
- var _i, _len, _ref, _results;
- _ref = Util.findGearsInsidePolygon(this.points, acknowledgedGears);
- _results = [];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- gear = _ref[_i];
- _results.push(gear.id);
- }
- return _results;
- }).call(this));
- if (Object.keys(this.innerGearIds).length < 2) {
- return false;
- }
- this.direction = Util.findDirection(this.points);
- this.supportingGearIds = this.findSupportingGearIds(acknowledgedGears);
- return this.update(board);
- };
-
- Chain.prototype.clone = function() {
- var copy;
- copy = new Chain(this.points, this.id, this.group, this.level, Util.clone(this.connections));
- copy.segments = Util.clone(this.segments);
- copy.ignoredGearIds = Util.clone(this.ignoredGearIds);
- copy.innerGearIds = Util.clone(this.innerGearIds);
- copy.direction = this.direction;
- copy.supportingGearIds = Util.clone(this.supportingGearIds);
- return copy;
- };
-
- Chain.fromObject = function(obj) {
- var chain, createSegment, p, points, segment;
- createSegment = function(obj) {
- if (obj.center != null) {
- return ArcSegment.fromObject(obj);
- } else {
- return LineSegment.fromObject(obj);
- }
- };
- points = (function() {
- var _i, _len, _ref, _results;
- _ref = obj.points;
- _results = [];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- p = _ref[_i];
- _results.push(new Point(p.x, p.y));
- }
- return _results;
- })();
- chain = new Chain(points, obj.id, obj.group, obj.level, obj.connections);
- chain.segments = (function() {
- var _i, _len, _ref, _results;
- _ref = obj.segments;
- _results = [];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- segment = _ref[_i];
- _results.push(createSegment(segment));
- }
- return _results;
- })();
- chain.ignoredGearIds = obj.ignoredGearIds;
- chain.innerGearIds = obj.innerGearIds;
- chain.direction = obj.direction;
- chain.supportingGearIds = obj.supportingGearIds;
- return chain;
- };
-
- return Chain;
-
- })();
-
- window.gearsketch.model.Chain = Chain;
-
- Board = (function() {
- var AXIS_RADIUS, ConnectionType, EPSILON, MIN_STACKED_GEARS_TEETH_DIFFERENCE, MODULE, SNAPPING_DISTANCE;
-
- MODULE = Util.MODULE;
-
- AXIS_RADIUS = Util.AXIS_RADIUS;
-
- MIN_STACKED_GEARS_TEETH_DIFFERENCE = Util.MIN_STACKED_GEARS_TEETH_DIFFERENCE;
-
- SNAPPING_DISTANCE = Util.SNAPPING_DISTANCE;
-
- EPSILON = Util.EPSILON;
-
- ConnectionType = {
- ANY: "any",
- MESHING: "meshing",
- AXIS: "axis",
- CHAIN_INSIDE: "chain_inside",
- CHAIN_OUTSIDE: "chain_outside"
- };
-
- function Board(gears, chains) {
- this.gears = gears != null ? gears : {};
- this.chains = chains != null ? chains : {};
- }
-
- Board.prototype.restore = function(board) {
- var gear, id, _ref;
- _ref = this.gears;
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- gear = _ref[id];
- gear.restore(board.gears[id]);
- }
- return this.chains = board.chains;
- };
-
- Board.prototype.restoreAfterDemo = function(board) {
- this.gears = board.gears;
- return this.chains = board.chains;
- };
-
- Board.prototype.clear = function() {
- this.gears = {};
- return this.chains = {};
- };
-
- Board.prototype.getNextGroup = function() {
- var gear, id, nextGroup, _ref;
- nextGroup = 0;
- _ref = this.gears;
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- gear = _ref[id];
- nextGroup = Math.max(nextGroup, gear.group + 1);
- }
- return nextGroup;
- };
-
- Board.prototype.getGears = function() {
- return this.gears;
- };
-
- Board.prototype.getGearList = function() {
- var gear, id, _ref, _results;
- _ref = this.gears;
- _results = [];
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- gear = _ref[id];
- _results.push(gear);
- }
- return _results;
- };
-
- Board.prototype.getAcknowledgedGears = function(ignoredGearIds) {
- var acknowledgedGears, gear, id, _ref;
- acknowledgedGears = {};
- _ref = this.gears;
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- gear = _ref[id];
- if (!(id in ignoredGearIds)) {
- acknowledgedGears[id] = gear;
- }
- }
- return acknowledgedGears;
- };
-
- Board.prototype.getLevelScore = function(gear) {
- return 1000 * gear.group + gear.level;
- };
-
- Board.prototype.getGearsSortedByGroupAndLevel = function(gears) {
- var _this = this;
- if (gears == null) {
- gears = this.getGearList();
- }
- return gears.sort(function(g1, g2) {
- return _this.getLevelScore(g1) - _this.getLevelScore(g2);
- });
- };
-
- Board.prototype.removeConnection = function(turningObject1, turningObject2) {
- delete turningObject1.connections[turningObject2.id];
- return delete turningObject2.connections[turningObject1.id];
- };
-
- Board.prototype.removeAllConnections = function(turningObject) {
- var neighbor, neighborId, _ref;
- _ref = turningObject.connections;
- for (neighborId in _ref) {
- if (!__hasProp.call(_ref, neighborId)) continue;
- neighbor = this.getTurningObjects()[neighborId];
- this.removeConnection(turningObject, neighbor);
- }
- return this.updateGroupsAndLevels();
- };
-
- Board.prototype.findNearestAxis = function(gear) {
- var candidate, distance, id, nearestAxis, shortestDistance, _ref;
- nearestAxis = null;
- shortestDistance = Number.MAX_VALUE;
- _ref = this.gears;
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- candidate = _ref[id];
- if (candidate !== gear) {
- distance = gear.location.distance(candidate.location);
- if (!nearestAxis || distance < (shortestDistance - EPSILON) || (distance < (shortestDistance + EPSILON) && candidate.numberOfTeeth < nearestAxis.numberOfTeeth)) {
- nearestAxis = candidate;
- shortestDistance = distance;
- }
- }
- }
- return nearestAxis;
- };
-
- Board.prototype.updateGroupsAndLevelsFrom = function(turningObjectId, group, level, updatedGroups, updatedLevels) {
- var connectionType, connections, gear, neighbor, neighborId, sameLevelConnectionTypes, turningObject, _results;
- turningObject = this.getTurningObjects()[turningObjectId];
- updatedGroups[turningObjectId] = group;
- updatedLevels[turningObjectId] = level;
- connections = turningObject.connections;
- sameLevelConnectionTypes = [ConnectionType.MESHING, ConnectionType.CHAIN_INSIDE, ConnectionType.CHAIN_OUTSIDE];
- _results = [];
- for (neighborId in connections) {
- if (!__hasProp.call(connections, neighborId)) continue;
- connectionType = connections[neighborId];
- if (!(neighborId in updatedGroups)) {
- if (__indexOf.call(sameLevelConnectionTypes, connectionType) >= 0) {
- _results.push(this.updateGroupsAndLevelsFrom(neighborId, group, level, updatedGroups, updatedLevels));
- } else {
- gear = this.gears[turningObjectId];
- neighbor = this.gears[neighborId];
- if (gear.numberOfTeeth > neighbor.numberOfTeeth) {
- _results.push(this.updateGroupsAndLevelsFrom(neighborId, group, level + 1, updatedGroups, updatedLevels));
- } else {
- _results.push(this.updateGroupsAndLevelsFrom(neighborId, group, level - 1, updatedGroups, updatedLevels));
- }
- }
- } else {
- _results.push(void 0);
- }
- }
- return _results;
- };
-
- Board.prototype.updateGroupsAndLevels = function() {
- var group, id, turningObject, updatedGroups, updatedLevels, _ref, _ref1;
- updatedGroups = {};
- updatedLevels = {};
- group = 0;
- _ref = this.gears;
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- if (!(id in updatedGroups)) {
- this.updateGroupsAndLevelsFrom(id, group, 0, updatedGroups, updatedLevels);
- group++;
- }
- }
- _ref1 = this.getTurningObjects();
- for (id in _ref1) {
- if (!__hasProp.call(_ref1, id)) continue;
- turningObject = _ref1[id];
- turningObject.group = updatedGroups[id];
- turningObject.level = updatedLevels[id];
- }
- return null;
- };
-
- Board.prototype.addConnection = function(turningObject1, turningObject2, connectionType) {
- turningObject1.connections[turningObject2.id] = connectionType;
- turningObject2.connections[turningObject1.id] = connectionType;
- return this.updateGroupsAndLevels();
- };
-
- Board.prototype.findMeshingNeighbors = function(gear) {
- var candidate, candidateId, meshingNeighbors, _ref;
- meshingNeighbors = [];
- _ref = this.gears;
- for (candidateId in _ref) {
- if (!__hasProp.call(_ref, candidateId)) continue;
- candidate = _ref[candidateId];
- if (candidate !== gear && gear.edgeDistance(candidate) < EPSILON) {
- if ((candidate.group !== gear.group) || (candidate.level === gear.level)) {
- meshingNeighbors.push(candidate);
- }
- }
- }
- return meshingNeighbors;
- };
-
- Board.prototype.findRelativeAlignment = function(gear1, gear2) {
- var angle1, angle2, p1, p2, phase1, phase2, phaseSum, r1, r2, shift1, shift2, toothAngle1, toothAngle2;
- p1 = gear1.location;
- r1 = gear1.rotation;
- p2 = gear2.location;
- r2 = gear2.rotation;
- angle1 = Math.atan2(p2.y - p1.y, p2.x - p1.x);
- angle2 = angle1 + Math.PI;
- shift1 = Util.mod(angle1 - r1, 2 * Math.PI);
- shift2 = Util.mod(angle2 - r2, 2 * Math.PI);
- toothAngle1 = (2 * Math.PI) / gear1.numberOfTeeth;
- toothAngle2 = (2 * Math.PI) / gear2.numberOfTeeth;
- phase1 = (shift1 % toothAngle1) / toothAngle1;
- phase2 = (shift2 % toothAngle2) / toothAngle2;
- phaseSum = (phase1 + phase2) % 1;
- return (phaseSum - 0.25) * toothAngle1;
- };
-
- Board.prototype.alignGearTeeth = function(rotatingGear, meshingGear) {
- return rotatingGear.rotation += this.findRelativeAlignment(rotatingGear, meshingGear);
- };
-
- Board.prototype.areMeshingGearsAligned = function(gear1, gear2) {
- return Math.abs(this.findRelativeAlignment(gear1, gear2)) < EPSILON;
- };
-
- Board.prototype.rotateTurningObjectsFrom = function(turningObject, angle, rotatedTurningObjectIds) {
- var connectionType, neighbor, neighborId, ratio, _ref, _results;
- if (!(turningObject.id in rotatedTurningObjectIds)) {
- turningObject.rotation = Util.mod(turningObject.rotation + angle, 2 * Math.PI);
- rotatedTurningObjectIds[turningObject.id] = true;
- }
- _ref = turningObject.connections;
- _results = [];
- for (neighborId in _ref) {
- if (!__hasProp.call(_ref, neighborId)) continue;
- connectionType = _ref[neighborId];
- neighbor = this.getTurningObjects()[neighborId];
- if (!(neighborId in rotatedTurningObjectIds)) {
- ratio = this.calculateRatio(turningObject, neighbor, connectionType);
- _results.push(this.rotateTurningObjectsFrom(neighbor, angle * ratio, rotatedTurningObjectIds));
- } else {
- _results.push(void 0);
- }
- }
- return _results;
- };
-
- Board.prototype.alignMeshingGears = function(gear) {
- var angle, neighbor, neighbors, r, rotatedGearIds, _i, _len, _results;
- rotatedGearIds = {};
- rotatedGearIds[gear.id] = true;
- neighbors = this.findMeshingNeighbors(gear);
- _results = [];
- for (_i = 0, _len = neighbors.length; _i < _len; _i++) {
- neighbor = neighbors[_i];
- this.addConnection(gear, neighbor, ConnectionType.MESHING);
- r = neighbor.rotation;
- this.alignGearTeeth(neighbor, gear);
- angle = neighbor.rotation - r;
- rotatedGearIds[neighbor.id] = true;
- _results.push(this.rotateTurningObjectsFrom(neighbor, angle, rotatedGearIds));
- }
- return _results;
- };
-
- Board.prototype.connectToAxis = function(upperGear, lowerGear) {
- this.addConnection(upperGear, lowerGear, ConnectionType.AXIS);
- upperGear.location = lowerGear.location.clone();
- upperGear.rotation = lowerGear.rotation;
- return this.alignMeshingGears(upperGear);
- };
-
- Board.prototype.findNearestNeighbor = function(gear, gearIdsToIgnore) {
- var edgeDistance, nearestNeighbor, neighbor, neighborId, shortestEdgeDistance, _ref;
- if (gearIdsToIgnore == null) {
- gearIdsToIgnore = {};
- }
- nearestNeighbor = null;
- shortestEdgeDistance = Number.MAX_VALUE;
- _ref = this.gears;
- for (neighborId in _ref) {
- if (!__hasProp.call(_ref, neighborId)) continue;
- neighbor = _ref[neighborId];
- if (neighbor !== gear && !(neighborId in gearIdsToIgnore)) {
- edgeDistance = gear.edgeDistance(neighbor);
- if (edgeDistance < shortestEdgeDistance) {
- nearestNeighbor = neighbor;
- shortestEdgeDistance = edgeDistance;
- }
- }
- }
- return nearestNeighbor;
- };
-
- Board.prototype.connectToOneMeshingGear = function(gear, meshingGear) {
- var angle, delta;
- delta = gear.location.minus(meshingGear.location);
- angle = Math.atan2(delta.y, delta.x);
- gear.location = meshingGear.location.plus(Point.polar(angle, gear.pitchRadius + meshingGear.pitchRadius));
- this.alignGearTeeth(gear, meshingGear);
- return this.addConnection(gear, meshingGear, ConnectionType.MESHING);
- };
-
- Board.prototype.connectToTwoMeshingGears = function(gear, meshingGear1, meshingGear2) {
- var a, d, h, p0, p1, p2, p3_1, p3_2, p3x1, p3x2, p3y1, p3y2, r0, r1;
- p0 = meshingGear1.location;
- p1 = meshingGear2.location;
- r0 = meshingGear1.pitchRadius + gear.pitchRadius;
- r1 = meshingGear2.pitchRadius + gear.pitchRadius;
- d = p0.distance(p1);
- if (r0 + r1 < d || p0.distance(p1) < EPSILON) {
- if (gear.edgeDistance(meshingGear1) < gear.edgeDistance(meshingGear2)) {
- this.connectToOneMeshingGear(gear, meshingGear1);
- return;
- } else {
- this.connectToOneMeshingGear(gear, meshingGear2);
- return;
- }
- }
- a = (r0 * r0 - r1 * r1 + d * d) / (2 * d);
- h = Math.sqrt(r0 * r0 - a * a);
- p2 = p0.plus(p1.minus(p0).times(a / d));
- p3x1 = p2.x + h * (p1.y - p0.y) / d;
- p3y1 = p2.y - h * (p1.x - p0.x) / d;
- p3x2 = p2.x - h * (p1.y - p0.y) / d;
- p3y2 = p2.y + h * (p1.x - p0.x) / d;
- p3_1 = new Point(p3x1, p3y1);
- p3_2 = new Point(p3x2, p3y2);
- if (gear.location.distance(p3_1) < gear.location.distance(p3_2)) {
- gear.location = p3_1;
- } else {
- gear.location = p3_2;
- }
- return this.alignMeshingGears(gear);
- };
-
- Board.prototype.doChainsCrossNonSupportingGears = function() {
- var chain, id, _ref;
- _ref = this.chains;
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- chain = _ref[id];
- if (chain.crossesNonSupportingGears(this)) {
- return true;
- }
- }
- return false;
- };
-
- Board.prototype.doChainsCrossEachOther = function(c1, c2) {
- if ((c1.group !== c2.group) || (c1.level === c2.level)) {
- if (c1.distanceToChain(c2) < Chain.WIDTH) {
- return true;
- }
- }
- return false;
- };
-
- Board.prototype.doesChainCrossAnyOtherChain = function(chain) {
- var chain2, id2, _ref;
- _ref = this.chains;
- for (id2 in _ref) {
- if (!__hasProp.call(_ref, id2)) continue;
- chain2 = _ref[id2];
- if (chain !== chain2) {
- if (this.doChainsCrossEachOther(chain, chain2)) {
- return true;
- }
- }
- }
- return false;
- };
-
- Board.prototype.doAnyChainsCrossEachOther = function() {
- var c1, c2, chain, chainList, i, id, j, numberOfChains, _i, _j, _ref, _ref1;
- chainList = (function() {
- var _ref, _results;
- _ref = this.chains;
- _results = [];
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- chain = _ref[id];
- _results.push(chain);
- }
- return _results;
- }).call(this);
- numberOfChains = chainList.length;
- if (numberOfChains < 2) {
- return false;
- }
- for (i = _i = 0, _ref = numberOfChains - 1; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- for (j = _j = _ref1 = i + 1; _ref1 <= numberOfChains ? _j < numberOfChains : _j > numberOfChains; j = _ref1 <= numberOfChains ? ++_j : --_j) {
- c1 = chainList[i];
- c2 = chainList[j];
- if (this.doChainsCrossEachOther(c1, c2)) {
- return true;
- }
- }
- }
- return false;
- };
-
- Board.prototype.areAllMeshingGearsAligned = function() {
- var g1, g2, gears, i, j, numberOfGears, _i, _j, _ref, _ref1;
- gears = this.getGearList();
- numberOfGears = gears.length;
- if (numberOfGears < 2) {
- return true;
- }
- for (i = _i = 0, _ref = numberOfGears - 1; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- for (j = _j = _ref1 = i + 1; _ref1 <= numberOfGears ? _j < numberOfGears : _j > numberOfGears; j = _ref1 <= numberOfGears ? ++_j : --_j) {
- g1 = gears[i];
- g2 = gears[j];
- if (g1.connections[g2.id] === ConnectionType.MESHING) {
- if (!this.areMeshingGearsAligned(g1, g2)) {
- return false;
- }
- }
- }
- }
- return true;
- };
-
- Board.prototype.calculateRatio = function(turningObject1, turningObject2, connectionType) {
- if (connectionType === ConnectionType.AXIS) {
- return 1;
- } else if ((connectionType === ConnectionType.MESHING) || (connectionType === ConnectionType.CHAIN_OUTSIDE)) {
- return -turningObject1.getCircumference() / turningObject2.getCircumference();
- } else {
- return turningObject1.getCircumference() / turningObject2.getCircumference();
- }
- };
-
- Board.prototype.calculatePathRatio = function(path) {
- var connectionType, i, pathLength, ratio, turningObject1, turningObject2, _i, _ref;
- ratio = 1;
- pathLength = path.length;
- for (i = _i = 0, _ref = pathLength - 1; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- turningObject1 = path[i];
- turningObject2 = path[i + 1];
- connectionType = turningObject1.connections[turningObject2.id];
- ratio *= this.calculateRatio(turningObject1, turningObject2, connectionType);
- }
- return ratio;
- };
-
- Board.prototype.areConnectionRatiosConsistent = function() {
- var path, pathName, paths, ratio, ratios, _i, _len;
- ratios = {};
- paths = Util.findAllSimplePathsBetweenNeighbors(this.getTurningObjects());
- for (_i = 0, _len = paths.length; _i < _len; _i++) {
- path = paths[_i];
- pathName = "" + path[0].id + "-" + path[path.length - 1].id;
- ratio = this.calculatePathRatio(path);
- if (ratios[pathName] == null) {
- ratios[pathName] = ratio;
- } else {
- if (Math.abs(ratios[pathName] - ratio) > EPSILON) {
- return false;
- }
- }
- }
- return true;
- };
-
- Board.prototype.isBoardValid = function() {
- var axisDistance, combinedOuterRadius, gear1, gear2, group1, group2, id1, id2, level1, level2, maxOuterRadius, _ref, _ref1;
- _ref = this.gears;
- for (id1 in _ref) {
- if (!__hasProp.call(_ref, id1)) continue;
- gear1 = _ref[id1];
- group1 = gear1.group;
- level1 = gear1.level;
- _ref1 = this.gears;
- for (id2 in _ref1) {
- if (!__hasProp.call(_ref1, id2)) continue;
- gear2 = _ref1[id2];
- if (gear1 !== gear2) {
- group2 = gear2.group;
- level2 = gear2.level;
- axisDistance = gear1.location.distance(gear2.location);
- maxOuterRadius = Math.max(gear1.outerRadius, gear2.outerRadius);
- combinedOuterRadius = gear1.outerRadius + gear2.outerRadius;
- if (axisDistance < EPSILON) {
- if ((group1 !== group2) || (level1 === level2)) {
- return false;
- }
- } else if (group1 === group2 && level1 === level2 && (gear1.connections[gear2.id] == null)) {
- if (axisDistance < combinedOuterRadius) {
- return false;
- }
- } else if (axisDistance < maxOuterRadius + AXIS_RADIUS) {
- return false;
- }
- }
- }
- }
- return !this.doChainsCrossNonSupportingGears() && !this.doAnyChainsCrossEachOther() && this.areAllMeshingGearsAligned() && this.areConnectionRatiosConsistent();
- };
-
- Board.prototype.placeGear = function(gear, location) {
- var chain, id, nearestAxis, neighbor1, neighbor2, oldBoard, _ref;
- oldBoard = this.clone();
- this.removeAllConnections(gear);
- gear.location = location.clone();
- nearestAxis = this.findNearestAxis(gear);
- if (nearestAxis && gear.location.distance(nearestAxis.location) < SNAPPING_DISTANCE && nearestAxis.numberOfTeeth - gear.numberOfTeeth > MIN_STACKED_GEARS_TEETH_DIFFERENCE) {
- this.connectToAxis(gear, nearestAxis);
- } else {
- neighbor1 = this.findNearestNeighbor(gear);
- if (neighbor1 && gear.edgeDistance(neighbor1) < SNAPPING_DISTANCE) {
- neighbor2 = this.findNearestNeighbor(gear, Util.makeSet(neighbor1.id));
- if (neighbor2 && gear.edgeDistance(neighbor2) < SNAPPING_DISTANCE) {
- this.connectToTwoMeshingGears(gear, neighbor1, neighbor2);
- } else {
- this.connectToOneMeshingGear(gear, neighbor1);
- }
- }
- }
- _ref = this.chains;
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- chain = _ref[id];
- if (chain.update(this)) {
- this.updateChainConnections(chain);
- } else {
- this.restore(oldBoard);
- return false;
- }
- }
- if (this.isBoardValid()) {
- return true;
- } else {
- this.restore(oldBoard);
- return false;
- }
- };
-
- Board.prototype.addGearToChains = function(gear) {
- var chain, id, _ref, _results;
- _ref = this.chains;
- _results = [];
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- chain = _ref[id];
- if (Util.isPointInsidePolygon(gear.location, chain.toPolygon())) {
- _results.push(chain.innerGearIds[gear.id] = true);
- } else {
- _results.push(void 0);
- }
- }
- return _results;
- };
-
- Board.prototype.removeGearFromChains = function(gear) {
- var chain, id, _ref, _results;
- _ref = this.chains;
- _results = [];
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- chain = _ref[id];
- if (!chain.removeGear(gear, this) || this.doesChainCrossAnyOtherChain(chain)) {
- _results.push(this.removeChain(chain));
- } else {
- _results.push(this.updateChainConnections(chain));
- }
- }
- return _results;
- };
-
- Board.prototype.addGear = function(gear) {
- var oldBoard;
- oldBoard = this.clone();
- gear.group = this.getNextGroup();
- this.gears[gear.id] = gear;
- this.addGearToChains(gear);
- if (!this.placeGear(gear, gear.location)) {
- this.removeGear(gear);
- this.restore(oldBoard);
- return false;
- } else {
- return true;
- }
- };
-
- Board.prototype.removeGear = function(gear) {
- this.removeAllConnections(gear);
- delete this.gears[gear.id];
- return this.removeGearFromChains(gear);
- };
-
- Board.prototype.getGearAt = function(location, candidates) {
- var candidate, distance, gear, id;
- if (candidates == null) {
- candidates = this.gears;
- }
- gear = null;
- for (id in candidates) {
- if (!__hasProp.call(candidates, id)) continue;
- candidate = candidates[id];
- distance = location.distance(candidate.location);
- if (distance < candidate.outerRadius) {
- if (!gear || candidate.numberOfTeeth < gear.numberOfTeeth) {
- gear = candidate;
- }
- }
- }
- return gear;
- };
-
- Board.prototype.isTopLevelGear = function(gear) {
- var connectionType, id, _ref;
- _ref = gear.connections;
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- connectionType = _ref[id];
- if (connectionType === ConnectionType.AXIS && this.gears[id].level > gear.level) {
- return false;
- }
- }
- return true;
- };
-
- Board.prototype.getTopLevelGears = function() {
- var gear, id, topLevelGears, _ref;
- topLevelGears = {};
- _ref = this.gears;
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- gear = _ref[id];
- if (this.isTopLevelGear(gear)) {
- topLevelGears[id] = gear;
- }
- }
- return topLevelGears;
- };
-
- Board.prototype.getTopLevelGearAt = function(location) {
- return this.getGearAt(location, this.getTopLevelGears());
- };
-
- Board.prototype.getGearWithId = function(id) {
- return this.gears[id];
- };
-
- Board.prototype.getGearsWithIds = function(ids) {
- var id, _i, _len, _results;
- _results = [];
- for (_i = 0, _len = ids.length; _i < _len; _i++) {
- id = ids[_i];
- _results.push(this.gears[id]);
- }
- return _results;
- };
-
- Board.prototype.rotateAllTurningObjects = function(delta) {
- var angle, gear, id, _ref, _results;
- _ref = this.gears;
- _results = [];
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- gear = _ref[id];
- if (gear.momentum) {
- angle = gear.momentum * (delta / 1000);
- _results.push(this.rotateTurningObjectsFrom(gear, angle, {}));
- } else {
- _results.push(void 0);
- }
- }
- return _results;
- };
-
- Board.prototype.addChainConnections = function(chain) {
- var gearId, _i, _len, _ref, _results;
- _ref = chain.supportingGearIds;
- _results = [];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- gearId = _ref[_i];
- if (gearId in chain.innerGearIds) {
- _results.push(this.addConnection(chain, this.getGearWithId(gearId), ConnectionType.CHAIN_INSIDE));
- } else {
- _results.push(this.addConnection(chain, this.getGearWithId(gearId), ConnectionType.CHAIN_OUTSIDE));
- }
- }
- return _results;
- };
-
- Board.prototype.updateChainConnections = function(chain) {
- this.removeAllConnections(chain);
- return this.addChainConnections(chain);
- };
-
- Board.prototype.addChain = function(chain) {
- var oldBoard;
- oldBoard = this.clone();
- this.chains[chain.id] = chain;
- if (chain.tighten(this)) {
- this.chains[chain.id] = chain;
- this.addChainConnections(chain);
- } else {
- this.restore(oldBoard);
- return false;
- }
- if (this.isBoardValid()) {
- return true;
- } else {
- this.restore(oldBoard);
- return false;
- }
- };
-
- Board.prototype.removeChain = function(chain) {
- this.removeAllConnections(chain);
- return delete this.chains[chain.id];
- };
-
- Board.prototype.getChains = function() {
- return this.chains;
- };
-
- Board.prototype.getChainsInGroupOnLevel = function(group, level) {
- var chain, id, _ref, _results;
- _ref = this.chains;
- _results = [];
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- chain = _ref[id];
- if ((chain.group === group) && (chain.level === level)) {
- _results.push(chain);
- }
- }
- return _results;
- };
-
- Board.prototype.getTurningObjects = function() {
- var chain, gear, id, turningObjects, _ref, _ref1;
- turningObjects = {};
- _ref = this.gears;
- for (id in _ref) {
- if (!__hasProp.call(_ref, id)) continue;
- gear = _ref[id];
- turningObjects[id] = gear;
- }
- _ref1 = this.chains;
- for (id in _ref1) {
- if (!__hasProp.call(_ref1, id)) continue;
- chain = _ref1[id];
- turningObjects[id] = chain;
- }
- return turningObjects;
- };
-
- Board.prototype.clone = function() {
- return {
- gears: Util.clone(this.gears),
- chains: Util.clone(this.chains)
- };
- };
-
- Board.fromObject = function(obj) {
- var board, chain, gear, id, _ref, _ref1;
- board = new Board();
- _ref = obj.gears;
- for (id in _ref) {
- gear = _ref[id];
- board.gears[id] = Gear.fromObject(gear);
- }
- _ref1 = obj.chains;
- for (id in _ref1) {
- chain = _ref1[id];
- board.chains[id] = Chain.fromObject(chain);
- }
- return board;
- };
-
- return Board;
-
- })();
-
- window.gearsketch.model.Board = Board;
-
- }).call(this);
-
- /*
- //@ sourceMappingURL=gearsketch_model.map
- */
|