paper.js/src/path/CurveLocation.js

243 lines
6.3 KiB
JavaScript
Raw Normal View History

2011-04-11 13:27:11 -04:00
/*
* Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
2011-04-11 13:27:11 -04:00
* http://paperjs.org/
*
* Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey
2011-04-11 13:27:11 -04:00
* http://lehni.org/ & http://jonathanpuckey.com/
*
2011-07-01 06:17:45 -04:00
* Distributed under the MIT license. See LICENSE file for details.
*
2011-04-11 13:27:11 -04:00
* All rights reserved.
*/
/**
* @name CurveLocation
*
* @class CurveLocation objects describe a location on {@link Curve}
* objects, as defined by the curve {@link #parameter}, a value between
* {@code 0} (beginning of the curve) and {@code 1} (end of the curve). If
* the curve is part of a {@link Path} item, its {@link #index} inside the
* {@link Path#curves} array is also provided.
2011-07-07 10:10:27 -04:00
*
* The class is in use in many places, such as
* {@link Path#getLocationAt(offset, isParameter)},
* {@link Path#getLocationOf(point)},
* {@link Path#getNearestLocation(point),
* {@link PathItem#getIntersections(path)},
* etc.
*/
2013-02-08 19:12:57 -05:00
var CurveLocation = this.CurveLocation = Base.extend(/** @lends CurveLocation# */{
2011-07-07 10:10:27 -04:00
// DOCS: CurveLocation class description: add these back when the mentioned
// functioned have been added: {@link Path#split(location)}
2011-05-23 11:39:26 -04:00
/**
* Creates a new CurveLocation object.
*
2011-05-23 11:39:26 -04:00
* @param {Curve} curve
* @param {Number} parameter
2011-05-23 11:39:26 -04:00
* @param {Point} point
*/
initialize: function(curve, parameter, point, distance) {
2013-04-22 22:11:42 -04:00
// Define this CurveLocation's unique id.
this._id = CurveLocation._id = (CurveLocation._id || 0) + 1;
2011-04-11 13:27:11 -04:00
this._curve = curve;
// Also store references to segment1 and segment2, in case path
// splitting / dividing is going to happen, in which case the segments
// can be used to determine the new curves, see #getCurve(true)
this._segment1 = curve._segment1;
this._segment2 = curve._segment2;
2011-04-11 13:27:11 -04:00
this._parameter = parameter;
this._point = point;
this._distance = distance;
2011-04-11 13:27:11 -04:00
},
/**
* The segment of the curve which is closer to the described location.
*
2011-05-23 11:39:26 -04:00
* @type Segment
* @bean
2011-04-11 13:27:11 -04:00
*/
getSegment: function() {
if (!this._segment) {
var curve = this.getCurve(),
2011-07-08 12:39:05 -04:00
parameter = this.getParameter();
2011-04-11 13:27:11 -04:00
if (parameter == 0) {
this._segment = curve._segment1;
2011-04-11 13:27:11 -04:00
} else if (parameter == 1) {
this._segment = curve._segment2;
2011-05-01 08:16:25 -04:00
} else if (parameter == null) {
2011-04-11 13:27:11 -04:00
return null;
} else {
// Determine the closest segment by comparing curve lengths
this._segment = curve.getLength(0, parameter)
< curve.getLength(parameter, 1)
? curve._segment1
: curve._segment2;
2011-04-11 13:27:11 -04:00
}
}
return this._segment;
},
/**
* The curve by which the location is defined.
*
2011-05-23 11:39:26 -04:00
* @type Curve
* @bean
2011-04-11 13:27:11 -04:00
*/
getCurve: function(/* uncached */) {
if (!this._curve || arguments[0]) {
// If we're asked to get the curve uncached, access current curve
// objects through segment1 / segment2. Since path splitting or
// dividing might have happened in the meantime, try segment1's
// curve, and see if _point lies on it still, otherwise assume it's
// the curve before segment2.
this._curve = this._segment1.getCurve();
if (this._curve.getParameterOf(this._point) == null)
this._curve = this._segment2.getPrevious().getCurve();
}
2011-04-11 13:27:11 -04:00
return this._curve;
},
/**
* The path this curve belongs to, if any.
*
2011-05-23 11:39:26 -04:00
* @type Item
* @bean
*/
getPath: function() {
var curve = this.getCurve();
return curve && curve._path;
},
2011-04-11 13:27:11 -04:00
/**
* The index of the curve within the {@link Path#curves} list, if the
2011-04-11 13:27:11 -04:00
* curve is part of a {@link Path} item.
*
2011-05-23 11:39:26 -04:00
* @type Index
* @bean
2011-04-11 13:27:11 -04:00
*/
getIndex: function() {
var curve = this.getCurve();
return curve && curve.getIndex();
2011-04-11 13:27:11 -04:00
},
/**
* The length of the path from its beginning up to the location described
* by this object.
*
* @type Number
2011-05-23 11:39:26 -04:00
* @bean
2011-04-11 13:27:11 -04:00
*/
getOffset: function() {
var path = this.getPath();
return path && path._getOffset(this);
2011-04-11 13:27:11 -04:00
},
/**
* The length of the curve from its beginning up to the location described
* by this object.
*
* @type Number
2011-05-23 11:39:26 -04:00
* @bean
2011-04-11 13:27:11 -04:00
*/
getCurveOffset: function() {
var curve = this.getCurve(),
parameter = this.getParameter();
return parameter != null && curve && curve.getLength(0, parameter);
2011-04-11 13:27:11 -04:00
},
/**
* The curve parameter, as used by various bezier curve calculations. It is
* value between {@code 0} (beginning of the curve) and {@code 1} (end of
* the curve).
*
* @type Number
2011-05-23 11:39:26 -04:00
* @bean
2011-04-11 13:27:11 -04:00
*/
getParameter: function(/* uncached */) {
if ((this._parameter == null || arguments[0]) && this._point) {
var curve = this.getCurve(arguments[0] && this._point);
this._parameter = curve && curve.getParameterOf(this._point);
}
return this._parameter;
2011-04-11 13:27:11 -04:00
},
/**
2011-05-23 11:39:26 -04:00
* The point which is defined by the {@link #curve} and
* {@link #parameter}.
*
2011-05-23 11:39:26 -04:00
* @type Point
* @bean
2011-04-11 13:27:11 -04:00
*/
getPoint: function() {
if (!this._point && this._parameter != null) {
var curve = this.getCurve();
this._point = curve && curve.getPointAt(this._parameter, true);
}
2011-04-11 13:27:11 -04:00
return this._point;
},
/**
2011-05-23 11:39:26 -04:00
* The tangential vector to the {@link #curve} at the given location.
*
2011-05-23 11:39:26 -04:00
* @type Point
* @bean
*/
getTangent: function() {
var parameter = this.getParameter(),
curve = this.getCurve();
return parameter != null && curve && curve.getTangentAt(parameter, true);
},
/**
2011-05-23 11:39:26 -04:00
* The normal vector to the {@link #curve} at the given location.
*
2011-05-23 11:39:26 -04:00
* @type Point
* @bean
*/
getNormal: function() {
var parameter = this.getParameter(),
curve = this.getCurve();
return parameter != null && curve && curve.getNormalAt(parameter, true);
},
/**
* The distance from the queried point to the returned location.
*
* @type Number
* @bean
*/
getDistance: function() {
return this._distance;
},
2012-12-30 13:53:09 -05:00
divide: function() {
var curve = this.getCurve(true);
return curve && curve.divide(this.getParameter(true));
},
split: function() {
var curve = this.getCurve(true);
return curve && curve.split(this.getParameter(true));
2012-12-30 13:53:09 -05:00
},
2011-05-23 11:39:26 -04:00
/**
* @return {String} A string representation of the curve location.
2011-05-23 11:39:26 -04:00
*/
2011-04-11 13:27:11 -04:00
toString: function() {
var parts = [],
point = this.getPoint(),
f = Formatter.instance;
if (point)
parts.push('point: ' + point);
2011-04-11 13:27:11 -04:00
var index = this.getIndex();
if (index != null)
parts.push('index: ' + index);
2011-04-11 13:27:11 -04:00
var parameter = this.getParameter();
if (parameter != null)
parts.push('parameter: ' + f.number(parameter));
if (this._distance != null)
parts.push('distance: ' + f.number(this._distance));
2011-05-02 06:23:42 -04:00
return '{ ' + parts.join(', ') + ' }';
2011-04-11 13:27:11 -04:00
}
});