Parse
File Parse pointlock.js
This runs the server-side parser and regenerates the documentation tree for this source file.
Source
class PointLock {
/* Linear lock.
A linear locked point can move _only_ along the given axis - the direction.
For dragging and interaction, the point is locked by the linear direction relative to _other_.
point.lock.linear(other)
The point may only move towards, or away from the other, disregarding the `point` direction. When `other` position changes, the linear lock will reflect this.
---
The point may only move in the direction of itself (forward or reverse)
point.lock.linear()
When rotating the point, the linear lock will reflect this.
---
Lock between two. Essentially the same as `other` (only `a`), but with a _max limit_.
point.lock.linear(a, b)
*/
constructor(point) {
this.point = point
this._facingOrigin = {x: point.x, y: point.y}
}
linear(a, b) {
if (b !== undefined) {
// perform a to b
return this.between(a, b)
}
if (a !== undefined) {
/* A point may only exist on the line extending from the center
of the given point (to infinity) */
return this.radial(a)
}
/* Locked to the pointing direction of self. Only moving _forward_ or _backward_ */
return this.facing()
}
facing() {
/* Locked to the pointing direction of self, assuming a _ray_ case from the center through
the tip of this (self) point. Only moving _forward_ or _backward_ but not sliding.
The constraint is applied only when this method is called.
*/
this._facingOrigin.radians = this.point.radians
const constrainedPoint = this.radial(this._facingOrigin)
// Must update after, else the rotation of the origin
// will be incorrect.
this._facingOrigin.x = constrainedPoint.x
this._facingOrigin.y = constrainedPoint.y
return constrainedPoint
}
between(a, b) {
/* self point may only exist between the two given points. */
const point = this.point
, originX = a.x
, originY = a.y
, dx = b.x - originX
, dy = b.y - originY
, lengthSquared = dx * dx + dy * dy
, f = ()=> {
let lr = (
(point.x - originX) * dx
+ (point.y - originY) * dy
) / lengthSquared
let _min = Math.min(1, lr)
return Math.max(0, _min)
}
const amount = lengthSquared === 0 ? 0 : f()
point.x = originX + amount * dx
point.y = originY + amount * dy
return point
}
radial(origin) {
/* cast from the origin, no sliding.
Note, this is already set from the existing origin. such that from the first call the sight-line
is assumed. When moving the point, the _origin_ can move freely, where _this_ self point
may only move along the cast ray from the origin.
luckily moving the origin doesn't affect the target (self) point.
*/
const point = this.point
const originX = origin.x
const originY = origin.y
const radians = origin.radians
const dx = Math.cos(radians)
const dy = Math.sin(radians)
const amount = (point.x - originX) * dx + (point.y - originY) * dy
point.x = originX + amount * dx
point.y = originY + amount * dy
return point
}
ray(origin, min=0, max=Infinity) {
/* cast from the origin, allowing sliding along the ray within the min and max bounds.
Bounds are signed multiples of origin.radius; negative values extend behind the origin.
1. (default 0) min is the minimum multiple.
2. (default Infinity) max is the maximum multiple.
Examples:
// lock to the outside of a point.
point.lock.ray(other, 1)
// lock one half inside.
point.lock.ray(other, .5, 1)
// axis lock
point.lock.ray(other, -1, 1)
// lock between 1/3 of the radius, to a max of 3X the radius.
point.lock.ray(other, .3, 3)
*/
const point = this.point
const originX = origin.x
const originY = origin.y
const radians = origin.radians
const radius = origin.radius
const dx = Math.cos(radians)
const dy = Math.sin(radians)
const projected = (point.x - originX) * dx + (point.y - originY) * dy
const minDistance = min * radius
const maxDistance = max === Infinity ? Infinity : max * radius
const amount = Math.max(minDistance, Math.min(maxDistance, projected))
point.x = originX + amount * dx
point.y = originY + amount * dy
return point
}
}
Polypoint.head.install(PointLock)
Polypoint.head.lazierProp('Point', function () {
return new PointLock(this)
}, 'lock')
copy