mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-01 02:38:43 -05:00
Implement Path#join(path) and add tests for it.
This commit is contained in:
parent
d02885cba7
commit
499c421021
2 changed files with 175 additions and 74 deletions
194
src/path/Path.js
194
src/path/Path.js
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
});
|
Loading…
Reference in a new issue