mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-06 04:42:15 -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
|
@ -109,6 +109,123 @@ var Path = this.Path = PathItem.extend({
|
||||||
return segment ? this._add(segment, index) : null;
|
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) {
|
draw: function(ctx, param) {
|
||||||
if (!param.compound)
|
if (!param.compound)
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
|
@ -178,7 +295,7 @@ var Path = this.Path = PathItem.extend({
|
||||||
var func = Array.prototype[name];
|
var func = Array.prototype[name];
|
||||||
this[name] = function() {
|
this[name] = function() {
|
||||||
return func.apply(this, arguments);
|
return func.apply(this, arguments);
|
||||||
}
|
};
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -207,7 +324,7 @@ var Path = this.Path = PathItem.extend({
|
||||||
this._add(Segment.read(segments, i, 1));
|
this._add(Segment.read(segments, i, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}, new function() { // Inject methods that require scoped privates
|
}, new function() { // Inject methods that require scoped privates
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -246,77 +363,6 @@ var Path = this.Path = PathItem.extend({
|
||||||
return {
|
return {
|
||||||
beans: true,
|
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() {
|
smooth: function() {
|
||||||
var segments = this._segments;
|
var segments = this._segments;
|
||||||
|
|
||||||
|
@ -424,7 +470,7 @@ var Path = this.Path = PathItem.extend({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}, new function() { // PostScript-style drawing commands
|
}, new function() { // PostScript-style drawing commands
|
||||||
|
|
||||||
function getCurrentSegment(that) {
|
function getCurrentSegment(that) {
|
||||||
|
|
|
@ -1 +1,56 @@
|
||||||
module('Path');
|
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