Parse

File Parse tethers-vec.js

This tree is parsed live from the source file.

Classes

  • {{ item.name }}

    • {{ key }}

Not Classes

{{ getTree() }}

Comments

{{ getTreeComments() }}

Source

            /*
files:
    ./windings.js
 */


const relPolarXY = function(primaryPoint, controlPoint, distance, spinRads) {
    /*
    get xy of the control point, relative to the {X,Y, Rot} of point A,
    using distance and relative angle.
     */
    // const primaryPoint = { x: 10, y: 10, radians: 1 };
    if(distance == undefined){
        distance = primaryPoint.distance2D(controlPoint)
    }
    const relative = { distance, spinRads };

    const totalRads = primaryPoint.radians + relative.spinRads;
    const dx = distance.x
          , dy = distance.y;

    const xRot = dx * Math.cos(totalRads) - dy * Math.sin(totalRads);
    const yRot = dx * Math.sin(totalRads) + dy * Math.cos(totalRads);

    return [primaryPoint.x + xRot, primaryPoint.y + yRot]
}


class PointTethers {
    /* Given a parent, bind a range of points by distance position.
    Call _step_ when visual updates are required.

        this.point = new Point(200, 200, 100)
        let cp = this.point.tethers.add({ x: 100, y: 50})

    Step:

        this.point.tethers.step()

    Render:

        this.point.pen.indicator(ctx, {color: '#336600'})
        this.point.tethers.points.pen.fill(ctx, '#33DDAA')
    */
    computeFunc = 'polar'
    constructor(point) {
        this.parent = point
        this.points = new PointList
        this.keepRotate = true
        this.windings = new PointWinding(this.parent)
    }

    add(pointData) {
        let cp = this.generate.apply(this, arguments)
        this.push(cp)
        return cp
    }

    onTipDragStart(ev) {
        let p = this.parent
        p.onTipDragStart && p.onTipDragStart.apply(p)
    }

    onTipDragMove(ev) {
        let p = this.parent
        p.onTipDragMove && p.onTipDragMove.apply(p)
    }

    onTipDragEnd(ev) {
        let p = this.parent
        p.onTipDragEnd && p.onTipDragEnd.apply(p)
    }

    generate(pointData) {
        /* Generate, store and return a new controller point */
        let _self = this;
        let point = this.parent
        let controlPoint;

        if(arguments.length == 0) {
            controlPoint = point.project()
        } else {
            controlPoint = new Point(...Array.from(arguments))
        }

        let record = function(cp, pp) {
            cp.controlPointsDistance = cp.distance2D(pp)
            cp.relRads = degToRad(calculateAngle360(pp, cp))
            // cp.radiansDiff = calculateAngleDiffWrapped(pp, cp)
        }

        record(controlPoint, point);

        controlPoint.onDragStart = function() {
            this._release = true;
            _self.onTipDragStart.apply(_self, arguments)
        }

        controlPoint.onDragMove = function() {
            record(this, point)
            _self.onTipDragMove.apply(_self, arguments)
        }

        controlPoint.onDragEnd = function() {
            // this.relRads = wrapRadians(v - point.radians);      // <- convert to local
            // function wrapRadians(t) {
            //   t = (t + Math.PI*2) % (Math.PI*2);
            //   return t < 0 ? t + Math.PI*2 : t;
            // }

            record(this, point)
            let v = degToRad(calculateAngle360(point, this))
            /* Ooft, took me a while.
            world to local mapping needs correcting.
            */
            this.relRads -= v + point.radians

            this._release = false;
            _self.onTipDragEnd.apply(_self, arguments)
        }

        return controlPoint
    }

    push(controlPoint) {
        this.points.push(controlPoint)
    }

    step(rotation=this.keepRotate){
        /* Unless the user is in control,
        Move any control point to the correct location,*/
        let pp = this.parent
        let computeFunc = this[`compute_${this.computeFunc}`]
        this.points.forEach((p,i)=>{
            if(p._release == true) { return } // mouse is down.
            p.xy = computeFunc(p, pp)
            // /* relative polar placement */
            // p.xy = relPolarXY(pp, p, p.controlPointsDistance, p.relRads)
            // /* relative xy position */
            // p.xy = this.point.add(p.controlPointsDistance).xy
        })
    }

    compute_polar(controlPoint, primaryPoint=this.parent) {
        /* relative polar placement */
        return relPolarXY(primaryPoint
                , controlPoint
                , controlPoint.controlPointsDistance
                , controlPoint.relRads)
    }

    compute_static(controlPoint, primaryPoint=this.parent){
        /* relative xy position */
        return primaryPoint.add(controlPoint.controlPointsDistance).xy
    }
}

Polypoint.head.deferredProp('Point', function tethers() {
        return new PointTethers(this)
    }
)
copy