mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-04 03:45:58 -05:00
Clean-up various Segment and Curve tests.
Moving functionality back to Path#toShape() since it was too specific, and missleading as part of the exposed Segment API.
This commit is contained in:
parent
71a7cc37e6
commit
9dab662a1f
3 changed files with 188 additions and 242 deletions
|
@ -133,6 +133,45 @@ var Curve = Base.extend(/** @lends Curve# */{
|
||||||
this._length = this._bounds = undefined;
|
this._length = this._bounds = undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a copy of the curve.
|
||||||
|
*
|
||||||
|
* @return {Curve}
|
||||||
|
*/
|
||||||
|
clone: function() {
|
||||||
|
return new Curve(this._segment1, this._segment2);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {String} a string representation of the curve
|
||||||
|
*/
|
||||||
|
toString: function() {
|
||||||
|
var parts = [ 'point1: ' + this._segment1._point ];
|
||||||
|
if (!this._segment1._handleOut.isZero())
|
||||||
|
parts.push('handle1: ' + this._segment1._handleOut);
|
||||||
|
if (!this._segment2._handleIn.isZero())
|
||||||
|
parts.push('handle2: ' + this._segment2._handleIn);
|
||||||
|
parts.push('point2: ' + this._segment2._point);
|
||||||
|
return '{ ' + parts.join(', ') + ' }';
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the curve from the path that it belongs to, by removing its
|
||||||
|
* second segment and merging its handle with the first segment.
|
||||||
|
* @return {Boolean} {@true if the curve was removed}
|
||||||
|
*/
|
||||||
|
remove: function() {
|
||||||
|
var removed = false;
|
||||||
|
if (this._path) {
|
||||||
|
var segment2 = this._segment2,
|
||||||
|
handleOut = segment2._handleOut;
|
||||||
|
removed = segment2.remove();
|
||||||
|
if (removed)
|
||||||
|
this._segment1._handleOut.set(handleOut.x, handleOut.y);
|
||||||
|
}
|
||||||
|
return removed;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The first anchor point of the curve.
|
* The first anchor point of the curve.
|
||||||
*
|
*
|
||||||
|
@ -322,7 +361,7 @@ var Curve = Base.extend(/** @lends Curve# */{
|
||||||
if (this._length == null) {
|
if (this._length == null) {
|
||||||
// Use simple point distance for straight curves
|
// Use simple point distance for straight curves
|
||||||
this._length = this.isLinear()
|
this._length = this.isLinear()
|
||||||
? this._segment2._point.getDistance(this._segment1._point)
|
? this.getVector().getLength()
|
||||||
: Curve.getLength(this.getValues(), 0, 1);
|
: Curve.getLength(this.getValues(), 0, 1);
|
||||||
}
|
}
|
||||||
return this._length;
|
return this._length;
|
||||||
|
@ -338,6 +377,17 @@ var Curve = Base.extend(/** @lends Curve# */{
|
||||||
return Curve.getArea(this.getValues());
|
return Curve.getArea(this.getValues());
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total direction of the curve as a vector pointing from
|
||||||
|
* {@link #point1} to {@link #point2}.
|
||||||
|
*
|
||||||
|
* @type Point
|
||||||
|
* @bean
|
||||||
|
*/
|
||||||
|
getVector: function() {
|
||||||
|
return this._segment2._point.subtract(this._segment1._point);
|
||||||
|
},
|
||||||
|
|
||||||
getPart: function(from, to) {
|
getPart: function(from, to) {
|
||||||
return new Curve(Curve.getPart(this.getValues(), from, to));
|
return new Curve(Curve.getPart(this.getValues(), from, to));
|
||||||
},
|
},
|
||||||
|
@ -347,67 +397,6 @@ var Curve = Base.extend(/** @lends Curve# */{
|
||||||
return Curve.getLength(this.getValues(), from, to);
|
return Curve.getLength(this.getValues(), from, to);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if this curve has any curve handles set.
|
|
||||||
*
|
|
||||||
* @return {Boolean} {@true if the curve has handles set}
|
|
||||||
* @see Curve#getHandle1()
|
|
||||||
* @see Curve#getHandle2()
|
|
||||||
* @see Segment#hasHandles()
|
|
||||||
* @see Path#hasHandles()
|
|
||||||
*/
|
|
||||||
hasHandles: function() {
|
|
||||||
return !this._segment1._handleOut.isZero()
|
|
||||||
|| !this._segment2._handleIn.isZero();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the curve's handles by setting their coordinates to zero,
|
|
||||||
* turning the curve into a straight line.
|
|
||||||
*/
|
|
||||||
clearHandles: function() {
|
|
||||||
this._segment1._handleOut.set(0, 0);
|
|
||||||
this._segment2._handleIn.set(0, 0);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if this curve appears as a straight line. This can mean that it
|
|
||||||
* has no handles defined, or that the handles run collinear with the line
|
|
||||||
* that connects the curve's start and end point, not falling outside of
|
|
||||||
* the line.
|
|
||||||
*
|
|
||||||
* @return {Boolean} {@true if the curve is linear}
|
|
||||||
* @see Segment#isLinear()
|
|
||||||
* @see Path#isLinear()
|
|
||||||
*/
|
|
||||||
isLinear: function() {
|
|
||||||
return Segment.isLinear(this._segment1, this._segment2);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the the two curves describe lines that are collinear, meaning
|
|
||||||
* they run in parallel.
|
|
||||||
*
|
|
||||||
* @param {Curve} curve the other curve to check against
|
|
||||||
* @return {Boolean} {@true if the two lines are collinear}
|
|
||||||
* @see Segment#isCollinear(segment)
|
|
||||||
*/
|
|
||||||
isCollinear: function(curve) {
|
|
||||||
return Segment.isCollinear(this._segment1, this._segment2,
|
|
||||||
curve._segment1, curve._segment2);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the curve describes an orthogonal arc, as used in the
|
|
||||||
* construction of circles and ellipses.
|
|
||||||
*
|
|
||||||
* @return {Boolean} {@true if the curve describes an orthogonal arc}
|
|
||||||
* @see Segment#isOrthogonalArc()
|
|
||||||
*/
|
|
||||||
isOrthogonalArc: function() {
|
|
||||||
return Segment.isOrthogonalArc(this._segment1, this._segment2);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all intersections between two {@link Curve} objects as an array
|
* Returns all intersections between two {@link Curve} objects as an array
|
||||||
* of {@link CurveLocation} objects.
|
* of {@link CurveLocation} objects.
|
||||||
|
@ -541,45 +530,14 @@ var Curve = Base.extend(/** @lends Curve# */{
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the curve from the path that it belongs to, by removing its
|
* Clears the curve's handles by setting their coordinates to zero,
|
||||||
* second segment and merging its handle with the first segment.
|
* turning the curve into a straight line.
|
||||||
* @return {Boolean} {@true if the curve was removed}
|
|
||||||
*/
|
*/
|
||||||
remove: function() {
|
clearHandles: function() {
|
||||||
var removed = false;
|
this._segment1._handleOut.set(0, 0);
|
||||||
if (this._path) {
|
this._segment2._handleIn.set(0, 0);
|
||||||
var segment2 = this._segment2,
|
|
||||||
handleOut = segment2._handleOut;
|
|
||||||
removed = segment2.remove();
|
|
||||||
if (removed)
|
|
||||||
this._segment1._handleOut.set(handleOut.x, handleOut.y);
|
|
||||||
}
|
|
||||||
return removed;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a copy of the curve.
|
|
||||||
*
|
|
||||||
* @return {Curve}
|
|
||||||
*/
|
|
||||||
clone: function() {
|
|
||||||
return new Curve(this._segment1, this._segment2);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {String} a string representation of the curve
|
|
||||||
*/
|
|
||||||
toString: function() {
|
|
||||||
var parts = [ 'point1: ' + this._segment1._point ];
|
|
||||||
if (!this._segment1._handleOut.isZero())
|
|
||||||
parts.push('handle1: ' + this._segment1._handleOut);
|
|
||||||
if (!this._segment2._handleIn.isZero())
|
|
||||||
parts.push('handle2: ' + this._segment2._handleIn);
|
|
||||||
parts.push('point2: ' + this._segment2._point);
|
|
||||||
return '{ ' + parts.join(', ') + ' }';
|
|
||||||
},
|
|
||||||
|
|
||||||
// Mess with indentation in order to get more line-space below...
|
|
||||||
statics: {
|
statics: {
|
||||||
getValues: function(segment1, segment2, matrix) {
|
getValues: function(segment1, segment2, matrix) {
|
||||||
var p1 = segment1._point,
|
var p1 = segment1._point,
|
||||||
|
@ -694,26 +652,6 @@ statics: {
|
||||||
&& isZero(v[4] - v[6]) && isZero(v[5] - v[7]));
|
&& isZero(v[4] - v[6]) && isZero(v[5] - v[7]));
|
||||||
},
|
},
|
||||||
|
|
||||||
isLinear: function(v) {
|
|
||||||
// See Segment#isLinear():
|
|
||||||
var p1x = v[0], p1y = v[1],
|
|
||||||
p2x = v[6], p2y = v[7],
|
|
||||||
l = new Point(p2x - p1x, p2y - p1y),
|
|
||||||
h1 = new Point(v[2] - p1x, v[3] - p1y),
|
|
||||||
h2 = new Point(v[4] - p2x, v[5] - p2y);
|
|
||||||
if (l.isZero()) {
|
|
||||||
return h1.isZero() && h2.isZero();
|
|
||||||
} else if (h1.isCollinear(l) && h2.isCollinear(l)) {
|
|
||||||
// Get the scalar projection of h1 and h2 onto l, and make sure they
|
|
||||||
// lie within l (note that h2 is reversed)
|
|
||||||
var div = l.dot(l),
|
|
||||||
p1 = l.dot(h1) / div,
|
|
||||||
p2 = l.dot(h2) / div;
|
|
||||||
return p1 >= 0 && p1 <= 1 && p2 <= 0 && p2 >= -1;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
isFlatEnough: function(v, tolerance) {
|
isFlatEnough: function(v, tolerance) {
|
||||||
// Thanks to Kaspar Fischer and Roger Willcocks for the following:
|
// Thanks to Kaspar Fischer and Roger Willcocks for the following:
|
||||||
// http://hcklbrrfnn.files.wordpress.com/2012/08/bez.pdf
|
// http://hcklbrrfnn.files.wordpress.com/2012/08/bez.pdf
|
||||||
|
@ -833,6 +771,8 @@ statics: {
|
||||||
},
|
},
|
||||||
/** @lends Curve# */{
|
/** @lends Curve# */{
|
||||||
/**
|
/**
|
||||||
|
* {@grouptitle Bounding Boxes}
|
||||||
|
*
|
||||||
* The bounding rectangle of the curve excluding stroke width.
|
* The bounding rectangle of the curve excluding stroke width.
|
||||||
*
|
*
|
||||||
* @name Curve#bounds
|
* @name Curve#bounds
|
||||||
|
@ -861,13 +801,88 @@ statics: {
|
||||||
* @type Rectangle
|
* @type Rectangle
|
||||||
* @ignore
|
* @ignore
|
||||||
*/
|
*/
|
||||||
}), /** @lends Curve# */{
|
}), new function() { // Injection scope for tests
|
||||||
|
function isLinear(l, h1, h2) {
|
||||||
|
if (h1.isZero() && h2.isZero()) {
|
||||||
|
// No handles.
|
||||||
|
return true;
|
||||||
|
} else if (l.isZero()) {
|
||||||
|
// Zero-length line, with some handles defined.
|
||||||
|
return false;
|
||||||
|
} else if (h1.isCollinear(l) && h2.isCollinear(l)) {
|
||||||
|
// Collinear handles. Project them onto line to see if they are
|
||||||
|
// within the line's range:
|
||||||
|
var div = l.dot(l),
|
||||||
|
p1 = l.dot(h1) / div,
|
||||||
|
p2 = l.dot(h2) / div;
|
||||||
|
return p1 >= 0 && p1 <= 1 && p2 <= 0 && p2 >= -1;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return /** @lends Curve# */{
|
||||||
|
/**
|
||||||
|
* {@grouptitle Tests}
|
||||||
|
*
|
||||||
|
* Checks if this curve has any curve handles set.
|
||||||
|
*
|
||||||
|
* @return {Boolean} {@true if the curve has handles set}
|
||||||
|
* @see Curve#handle1
|
||||||
|
* @see Curve#handle2
|
||||||
|
* @see Segment#hasHandles()
|
||||||
|
* @see Path#hasHandles()
|
||||||
|
*/
|
||||||
|
hasHandles: function() {
|
||||||
|
return !this._segment1._handleOut.isZero()
|
||||||
|
|| !this._segment2._handleIn.isZero();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this curve appears as a straight line. This can mean that
|
||||||
|
* it has no handles defined, or that the handles run collinear with the
|
||||||
|
* line that connects the curve's start and end point, not falling
|
||||||
|
* outside of the line.
|
||||||
|
*
|
||||||
|
* @return {Boolean} {@true if the curve is linear}
|
||||||
|
*/
|
||||||
|
isLinear: function() {
|
||||||
|
var seg1 = this._segment1,
|
||||||
|
seg2 = this._segment2;
|
||||||
|
return isLinear(seg2._point.subtract(seg1._point),
|
||||||
|
seg1._handleOut, seg2._handleIn);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the the two curves describe straight lines that are
|
||||||
|
* collinear, meaning they run in parallel.
|
||||||
|
*
|
||||||
|
* @param {Curve} curve the other curve to check against
|
||||||
|
* @return {Boolean} {@true if the two lines are collinear}
|
||||||
|
*/
|
||||||
|
isCollinear: function(curve) {
|
||||||
|
return this.isLinear() && curve.isLinear()
|
||||||
|
&& this.getVector().isCollinear(curve.getVector());
|
||||||
|
},
|
||||||
|
|
||||||
|
statics: {
|
||||||
|
isLinear: function(v) {
|
||||||
|
var p1x = v[0], p1y = v[1],
|
||||||
|
p2x = v[6], p2y = v[7];
|
||||||
|
return isLinear(new Point(p2x - p1x, p2y - p1y),
|
||||||
|
new Point(v[2] - p1x, v[3] - p1y),
|
||||||
|
new Point(v[4] - p2x, v[5] - p2y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, /** @lends Curve# */{
|
||||||
// Explicitly deactivate the creation of beans, as we have functions here
|
// Explicitly deactivate the creation of beans, as we have functions here
|
||||||
// that look like bean getters but actually read arguments.
|
// that look like bean getters but actually read arguments.
|
||||||
// See #getParameterOf(), #getLocationOf(), #getNearestLocation(), ...
|
// See #getParameterOf(), #getLocationOf(), #getNearestLocation(), ...
|
||||||
beans: false,
|
beans: false,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* {@grouptitle Positions on Curves}
|
||||||
|
*
|
||||||
* Calculates the curve time parameter of the specified offset on the path,
|
* Calculates the curve time parameter of the specified offset on the path,
|
||||||
* relative to the provided start parameter. If offset is a negative value,
|
* relative to the provided start parameter. If offset is a negative value,
|
||||||
* the parameter is searched to the left of the start parameter. If no start
|
* the parameter is searched to the left of the start parameter. If no start
|
||||||
|
@ -935,6 +950,14 @@ statics: {
|
||||||
return loc ? loc.getOffset() : null;
|
return loc ? loc.getOffset() : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the nearest location on the curve to the specified point.
|
||||||
|
*
|
||||||
|
* @function
|
||||||
|
* @param {Point} point the point for which we search the nearest location
|
||||||
|
* @return {CurveLocation} the location on the curve that's the closest to
|
||||||
|
* the specified point
|
||||||
|
*/
|
||||||
getNearestLocation: function(/* point */) {
|
getNearestLocation: function(/* point */) {
|
||||||
var point = Point.read(arguments),
|
var point = Point.read(arguments),
|
||||||
values = this.getValues(),
|
values = this.getValues(),
|
||||||
|
@ -967,6 +990,14 @@ statics: {
|
||||||
point.getDistance(pt));
|
point.getDistance(pt));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the nearest point on the curve to the specified point.
|
||||||
|
*
|
||||||
|
* @function
|
||||||
|
* @param {Point} point the point for which we search the nearest point
|
||||||
|
* @return {Point} the point on the curve that's the closest to the
|
||||||
|
* specified point
|
||||||
|
*/
|
||||||
getNearestPoint: function(/* point */) {
|
getNearestPoint: function(/* point */) {
|
||||||
return this.getNearestLocation.apply(this, arguments).getPoint();
|
return this.getNearestLocation.apply(this, arguments).getPoint();
|
||||||
}
|
}
|
||||||
|
@ -1050,7 +1081,6 @@ statics: {
|
||||||
*/
|
*/
|
||||||
},
|
},
|
||||||
new function() { // // Scope to inject various curve evaluation methods
|
new function() { // // Scope to inject various curve evaluation methods
|
||||||
|
|
||||||
var methods = ['getPoint', 'getTangent', 'getNormal', 'getWeightedTangent',
|
var methods = ['getPoint', 'getTangent', 'getNormal', 'getWeightedTangent',
|
||||||
'getWeightedNormal', 'getCurvature'];
|
'getWeightedNormal', 'getCurvature'];
|
||||||
return Base.each(methods,
|
return Base.each(methods,
|
||||||
|
@ -1183,8 +1213,7 @@ new function() { // Scope for methods that require private functions
|
||||||
return type === 2 ? new Point(y, -x) : new Point(x, y);
|
return type === 2 ? new Point(y, -x) : new Point(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return { statics: {
|
||||||
statics: true,
|
|
||||||
|
|
||||||
getLength: function(v, a, b) {
|
getLength: function(v, a, b) {
|
||||||
if (a === undefined)
|
if (a === undefined)
|
||||||
|
@ -1274,9 +1303,10 @@ new function() { // Scope for methods that require private functions
|
||||||
getCurvature: function(v, t) {
|
getCurvature: function(v, t) {
|
||||||
return evaluate(v, t, 3, false).x;
|
return evaluate(v, t, 3, false).x;
|
||||||
}
|
}
|
||||||
};
|
}};
|
||||||
},
|
},
|
||||||
new function() { // Scope for intersection using bezier fat-line clipping
|
new function() { // Scope for intersection using bezier fat-line clipping
|
||||||
|
|
||||||
function addLocation(locations, include, curve1, t1, point1, curve2, t2,
|
function addLocation(locations, include, curve1, t1, point1, curve2, t2,
|
||||||
point2) {
|
point2) {
|
||||||
var loc = new CurveLocation(curve1, t1, point1, curve2, t2, point2);
|
var loc = new CurveLocation(curve1, t1, point1, curve2, t2, point2);
|
||||||
|
|
|
@ -1406,15 +1406,47 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
topCenter;
|
topCenter;
|
||||||
|
|
||||||
function isCollinear(i, j) {
|
function isCollinear(i, j) {
|
||||||
return segments[i].isCollinear(segments[j]);
|
var seg1 = segments[i],
|
||||||
|
seg2 = seg1.getNext(),
|
||||||
|
seg3 = segments[j],
|
||||||
|
seg4 = seg3.getNext();
|
||||||
|
return seg1._handleOut.isZero() && seg2._handleIn.isZero()
|
||||||
|
&& seg3._handleOut.isZero() && seg4._handleIn.isZero()
|
||||||
|
&& seg2._point.subtract(seg1._point).isCollinear(
|
||||||
|
seg4._point.subtract(seg3._point));
|
||||||
}
|
}
|
||||||
|
|
||||||
function isOrthogonal(i) {
|
function isOrthogonal(i) {
|
||||||
return segments[i].isOrthogonal();
|
var seg2 = segments[i],
|
||||||
|
seg1 = seg2.getPrevious(),
|
||||||
|
seg3 = seg2.getNext();
|
||||||
|
return seg1._handleOut.isZero() && seg2._handleIn.isZero()
|
||||||
|
&& seg2._handleOut.isZero() && seg3._handleIn.isZero()
|
||||||
|
&& seg2._point.subtract(seg1._point).isOrthogonal(
|
||||||
|
seg3._point.subtract(seg2._point));
|
||||||
}
|
}
|
||||||
|
|
||||||
function isArc(i) {
|
function isArc(i) {
|
||||||
return segments[i].isOrthogonalArc();
|
var seg1 = segments[i],
|
||||||
|
seg2 = seg1.getNext(),
|
||||||
|
handle1 = seg1._handleOut,
|
||||||
|
handle2 = seg2._handleIn,
|
||||||
|
kappa = /*#=*/Numerical.KAPPA;
|
||||||
|
// Look at handle length and the distance to the imaginary corner
|
||||||
|
// point and see if it their relation is kappa.
|
||||||
|
if (handle1.isOrthogonal(handle2)) {
|
||||||
|
var pt1 = seg1._point,
|
||||||
|
pt2 = seg2._point,
|
||||||
|
// Find the corner point by intersecting the lines described
|
||||||
|
// by both handles:
|
||||||
|
corner = new Line(pt1, handle1, true).intersect(
|
||||||
|
new Line(pt2, handle2, true), true);
|
||||||
|
return corner && Numerical.isZero(handle1.getLength() /
|
||||||
|
corner.subtract(pt1).getLength() - kappa)
|
||||||
|
&& Numerical.isZero(handle2.getLength() /
|
||||||
|
corner.subtract(pt2).getLength() - kappa);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDistance(i, j) {
|
function getDistance(i, j) {
|
||||||
|
|
|
@ -251,62 +251,6 @@ var Segment = Base.extend(/** @lends Segment# */{
|
||||||
this._handleOut.set(0, 0);
|
this._handleOut.set(0, 0);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the curve that starts in this segment appears as a straight
|
|
||||||
* line. This can mean that it has no handles defined, or that the handles
|
|
||||||
* run collinear with the line that connects the curve's start and end
|
|
||||||
* point, not falling outside of the line.
|
|
||||||
*
|
|
||||||
* @return {Boolean} {@true if the curve starting in this segment is linear}
|
|
||||||
* @see Curve#isLinear()
|
|
||||||
* @see Path#isLinear()
|
|
||||||
*/
|
|
||||||
isLinear: function() {
|
|
||||||
return Segment.isLinear(this, this.getNext());
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the the two segments are the beginning of two lines that are
|
|
||||||
* collinear, meaning they run in parallel.
|
|
||||||
*
|
|
||||||
* @param {Segment} segment the other segment to check against
|
|
||||||
* @return {Boolean} {@true if the two lines are collinear}
|
|
||||||
* @see Curve#isCollinear(curve)
|
|
||||||
*/
|
|
||||||
isCollinear: function(segment) {
|
|
||||||
return Segment.isCollinear(this, this.getNext(),
|
|
||||||
segment, segment.getNext());
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO: Remove version with typo after a while (deprecated June 2015)
|
|
||||||
isColinear: '#isCollinear',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the segment is connecting two lines that are orthogonal,
|
|
||||||
* meaning they connect at an 90° angle.
|
|
||||||
*
|
|
||||||
* @return {Boolean} {@true if the two lines connected by this segment are
|
|
||||||
* orthogonal}
|
|
||||||
*/
|
|
||||||
isOrthogonal: function() {
|
|
||||||
return Segment.isOrthogonal(this.getPrevious(), this, this.getNext());
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the segment is the beginning of an orthogonal arc, as used in
|
|
||||||
* the construction of circles and ellipses.
|
|
||||||
*
|
|
||||||
* @return {Boolean} {@true if the segment is the beginning of an orthogonal
|
|
||||||
* arc}
|
|
||||||
* @see Curve#isOrthogonalArc()
|
|
||||||
*/
|
|
||||||
isOrthogonalArc: function() {
|
|
||||||
return Segment.isOrthogonalArc(this, this.getNext());
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO: Remove a while (deprecated August 2015)
|
|
||||||
isArc: '#isOrthogonalArc',
|
|
||||||
|
|
||||||
_selectionState: 0,
|
_selectionState: 0,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -561,65 +505,5 @@ var Segment = Base.extend(/** @lends Segment# */{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return coords;
|
return coords;
|
||||||
},
|
|
||||||
|
|
||||||
statics: {
|
|
||||||
// These statics are shared between Segment and Curve, for versions of
|
|
||||||
// these methods that are implemented in both places. Most of these
|
|
||||||
// methods relate more to the nature of curves than segments, but since
|
|
||||||
// curves are made out of segments, and segments are the main path data
|
|
||||||
// structure, while curves are 2nd class citizens, they are defined here
|
|
||||||
|
|
||||||
isLinear: function(seg1, seg2) {
|
|
||||||
var l = seg2._point.subtract(seg1._point),
|
|
||||||
h1 = seg1._handleOut,
|
|
||||||
h2 = seg2._handleIn;
|
|
||||||
if (l.isZero()) {
|
|
||||||
return h1.isZero() && h2.isZero();
|
|
||||||
} else if (h1.isCollinear(l) && h2.isCollinear(l)) {
|
|
||||||
var div = l.dot(l),
|
|
||||||
p1 = l.dot(h1) / div,
|
|
||||||
p2 = l.dot(h2) / div;
|
|
||||||
return p1 >= 0 && p1 <= 1 && p2 <= 0 && p2 >= -1;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
isCollinear: function(seg1, seg2, seg3, seg4) {
|
|
||||||
// TODO: This assumes !hasHandles(), while isLinear() allows handles!
|
|
||||||
return seg1._handleOut.isZero() && seg2._handleIn.isZero()
|
|
||||||
&& seg3._handleOut.isZero() && seg4._handleIn.isZero()
|
|
||||||
&& seg2._point.subtract(seg1._point).isCollinear(
|
|
||||||
seg4._point.subtract(seg3._point));
|
|
||||||
},
|
|
||||||
|
|
||||||
isOrthogonal: function(seg1, seg2, seg3) {
|
|
||||||
// TODO: This assumes !hasHandles(), while isLinear() allows handles!
|
|
||||||
return seg1._handleOut.isZero() && seg2._handleIn.isZero()
|
|
||||||
&& seg2._handleOut.isZero() && seg3._handleIn.isZero()
|
|
||||||
&& seg2._point.subtract(seg1._point).isOrthogonal(
|
|
||||||
seg3._point.subtract(seg2._point));
|
|
||||||
},
|
|
||||||
|
|
||||||
isOrthogonalArc: function(seg1, seg2) {
|
|
||||||
var handle1 = seg1._handleOut,
|
|
||||||
handle2 = seg2._handleIn,
|
|
||||||
kappa = /*#=*/Numerical.KAPPA;
|
|
||||||
// Look at handle length and the distance to the imaginary corner
|
|
||||||
// point and see if it their relation is kappa.
|
|
||||||
if (handle1.isOrthogonal(handle2)) {
|
|
||||||
var pt1 = seg1._point,
|
|
||||||
pt2 = seg2._point,
|
|
||||||
// Find the corner point by intersecting the lines described
|
|
||||||
// by both handles:
|
|
||||||
corner = new Line(pt1, handle1, true).intersect(
|
|
||||||
new Line(pt2, handle2, true), true);
|
|
||||||
return corner && Numerical.isZero(handle1.getLength() /
|
|
||||||
corner.subtract(pt1).getLength() - kappa)
|
|
||||||
&& Numerical.isZero(handle2.getLength() /
|
|
||||||
corner.subtract(pt2).getLength() - kappa);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue