Implement Path#join(path) and add tests for it.

This commit is contained in:
Jonathan Puckey 2011-04-11 23:30:08 +02:00
parent d02885cba7
commit 499c421021
2 changed files with 175 additions and 74 deletions

View file

@ -108,6 +108,123 @@ var Path = this.Path = PathItem.extend({
var segment = Segment.read(arguments, 1);
return segment ? this._add(segment, index) : null;
},
/**
* Reverses the segments of the path.
*/
reverse: function() {
this._segments.reverse();
},
join: function(path) {
if (path != null) {
var segments = path.segments;
var last1 = this.getLastSegment();
var last2 = path.getLastSegment();
if (last1.getPoint().equals(last2.getPoint()))
path.reverse();
var first2 = path.getFirstSegment();
if (last1.getPoint().equals(first2.getPoint())) {
last1.setHandleOut(first2.getHandleOut());
for (var i = 1, l = segments.length; i < l; i++)
this._add(segments[i]);
} else {
var first1 = this.getFirstSegment();
if (first1.getPoint().equals(first2.getPoint()))
path.reverse();
if (first1.getPoint().equals(last2.getPoint())) {
first1.setHandleIn(last2.getHandleIn());
// Prepend all segments from path except last one
for (var i = 0, l = segments.length - 1; i < l; i++)
this._add(segments[i], 0);
} else {
for (var i = 0, l = segments.length; i < l; i++)
this._add(segments[i]);
}
}
path.remove();
// Close if they touch in both places
var first1 = this.getFirstSegment();
last1 = this.getLastSegment();
if (last1.getPoint().equals(first1.getPoint())) {
first1.setHandleIn(last1.getHandleIn());
last1.remove();
this.closed = true;
}
return true;
}
return false;
},
// todo: getLocation(point, precision)
getLocation: function(length) {
var curves = this.getCurves();
var currentLength = 0;
for (var i = 0, l = curves.length; i < l; i++) {
var startLength = currentLength;
var curve = curves[i];
currentLength += curve.getLength();
if(currentLength >= length) {
// found the segment within which the length lies
var t = curve.getParameter(length - startLength);
return new CurveLocation(curve, t);
}
}
// Todo: is this the case for paper.js too?
// it may be that through impreciseness of getLength, that the end
// of the curves was missed:
if (length <= this.getLength()) {
var curve = curves[curves.length - 1];
return new CurveLocation(curve, 1);
}
return null;
},
getLength: function(/* location */) {
var location;
if(arguments.length)
location = arguments[0];
var curves = this.getCurves();
var index = location
? location.getIndex()
: curves.length;
if (index != -1) {
var length = 0;
for (var i = 0; i < index; i++)
length += curves[i].getLength();
var curve;
if (location) {
// Clone the curve as we're going to divide it to get the
// length. Without cloning it, this would modify the path.
curve = curves[index].clone();
curve.divide(location.getParameter());
length += curve.getLength();
}
return length;
}
return -1;
},
/**
* Returns the tangent to the path at the given length as a vector
* point.
*/
getTangent: function(length) {
var loc = this.getLocation(length);
return loc
? loc.getCurve().getTangent(loc.getParameter())
: null;
},
/**
* Returns the normal to the path at the given length as a vector point.
*/
getNormal: function(length) {
var loc = this.getLocation(length);
return loc
? loc.getCurve().getNormal(loc.getParameter())
: null;
},
draw: function(ctx, param) {
if (!param.compound)
@ -178,7 +295,7 @@ var Path = this.Path = PathItem.extend({
var func = Array.prototype[name];
this[name] = function() {
return func.apply(this, arguments);
}
};
}, {});
return {
@ -207,7 +324,7 @@ var Path = this.Path = PathItem.extend({
this._add(Segment.read(segments, i, 1));
}
}
}
};
}, new function() { // Inject methods that require scoped privates
/**
@ -245,77 +362,6 @@ var Path = this.Path = PathItem.extend({
return {
beans: true,
// todo: getLocation(point, precision)
getLocation: function(length) {
var curves = this.getCurves();
var currentLength = 0;
for (var i = 0, l = curves.length; i < l; i++) {
var startLength = currentLength;
var curve = curves[i];
currentLength += curve.getLength();
if(currentLength >= length) {
// found the segment within which the length lies
var t = curve.getParameter(length - startLength);
console.log(t, length - startLength, '??')
return new CurveLocation(curve, t);
}
}
// Todo: is this the case for paper.js too?
// it may be that through impreciseness of getLength, that the end
// of the curves was missed:
if (length <= this.getLength()) {
var curve = curves[curves.length - 1];
return new CurveLocation(curve, 1);
}
return null;
},
getLength: function(/* location */) {
var location;
if(arguments.length)
location = arguments[0];
var curves = this.getCurves();
var index = location
? location.getIndex()
: curves.length;
if (index != -1) {
var length = 0;
for (var i = 0; i < index; i++)
length += curves[i].getLength();
var curve;
if (location) {
// Clone the curve as we're going to divide it to get the
// length. Without cloning it, this would modify the path.
curve = curves[index].clone();
curve.divide(location.getParameter());
length += curve.getLength();
}
return length;
}
return -1;
},
/**
* Returns the tangent to the path at the given length as a vector
* point.
*/
getTangent: function(length) {
var loc = this.getLocation(length);
return loc
? loc.getCurve().getTangent(loc.getParameter())
: null;
},
/**
* Returns the normal to the path at the given length as a vector point.
*/
getNormal: function(length) {
var loc = this.getLocation(length);
return loc
? loc.getCurve().getNormal(loc.getParameter())
: null;
},
smooth: function() {
var segments = this._segments;
@ -424,7 +470,7 @@ var Path = this.Path = PathItem.extend({
}
}
}
}
};
}, new function() { // PostScript-style drawing commands
function getCurrentSegment(that) {

View file

@ -1 +1,56 @@
module('Path');
test('path.join(path)', function() {
var doc = new Document();
var path = new Path();
path.add(0, 0);
path.add(10, 0);
var path2 = new Path();
path2.add(10, 0);
path2.add(20, 10);
path.join(path2);
compareSegmentLists(path.segments, [new Segment(new Point(0, 0)),
new Segment(new Point(10, 0)), new Segment(new Point(20, 10))]);
equals(doc.activeLayer.children.length, 1);
var path = new Path();
path.add(0, 0);
path.add(10, 0);
var path2 = new Path();
path2.add(20, 10);
path2.add(10, 0);
path.join(path2);
compareSegmentLists(path.segments, [new Segment(new Point(0, 0)),
new Segment(new Point(10, 0)), new Segment(new Point(20, 10))]);
var path = new Path();
path.add(0, 0);
path.add(10, 0);
var path2 = new Path();
path2.add(30, 10);
path2.add(40, 0);
path.join(path2);
compareSegmentLists(path.segments, [new Segment(new Point(0, 0)),
new Segment(new Point(10, 0)), new Segment(new Point(30, 10)),
new Segment(new Point(40, 0))]);
var path = new Path();
path.add(0, 0);
path.add(10, 0);
path.add(20, 10);
var path2 = new Path();
path2.add(0, 0);
path2.add(10, 5);
path2.add(20, 10);
path.join(path2);
compareSegmentLists(path.segments, [new Segment(new Point(0, 0)),
new Segment(new Point(10, 0)), new Segment(new Point(20, 10)),
new Segment(new Point(10, 5))]);
equals(path.closed, true);
});