From 8254f3dbbbcd7cd4f1bb0e787d6601c145113734 Mon Sep 17 00:00:00 2001 From: "Val Erastov (xibyte)" Date: Wed, 11 Mar 2020 03:42:47 -0700 Subject: [PATCH] bezier curve tangent constraint --- web/app/math/bezier-cubic.js | 1 - web/app/sketcher/actions/constraintActions.js | 12 +- web/app/sketcher/constr/ANConstraints.js | 157 ++++++++++++++---- web/app/sketcher/constr/AlgNumSystem.js | 15 +- web/app/sketcher/shapes/arc.js | 3 - web/app/sketcher/shapes/bezier-curve.js | 13 ++ web/app/sketcher/shapes/circle.js | 2 - web/app/sketcher/shapes/point.js | 4 + 8 files changed, 160 insertions(+), 47 deletions(-) diff --git a/web/app/math/bezier-cubic.js b/web/app/math/bezier-cubic.js index e1f81d9b..04b080bf 100644 --- a/web/app/math/bezier-cubic.js +++ b/web/app/math/bezier-cubic.js @@ -1,5 +1,4 @@ import Vector from 'math/vector'; -import * as math from './math' export function LUT(a, b, cp1, cp2, scale) { scale = 1 / scale; diff --git a/web/app/sketcher/actions/constraintActions.js b/web/app/sketcher/actions/constraintActions.js index 87f46824..4bd8def6 100644 --- a/web/app/sketcher/actions/constraintActions.js +++ b/web/app/sketcher/actions/constraintActions.js @@ -44,7 +44,7 @@ export default [ selector: 'matchSequence', sequence: [ { - types: [Circle, Arc], + types: [Circle, Arc, BezierCurve], quantity: 1 }, { @@ -57,9 +57,13 @@ export default [ invoke: (ctx, matchedObjects) => { const {viewer} = ctx; - const [circle, line] = matchedObjects; - - const constraint = new AlgNumConstraint(ConstraintDefinitions.TangentLC, [line, circle]); + const [curve, line] = matchedObjects; + let constraint; + if (isInstanceOf(curve, BezierCurve) ) { + constraint = new AlgNumConstraint(ConstraintDefinitions.TangentLineBezier, [line, curve]); + } else { + constraint = new AlgNumConstraint(ConstraintDefinitions.TangentLC, [line, curve]); + } constraint.initConstants(); const pm = viewer.parametricManager; pm.add(constraint); diff --git a/web/app/sketcher/constr/ANConstraints.js b/web/app/sketcher/constr/ANConstraints.js index 3f89b942..1cb2f663 100644 --- a/web/app/sketcher/constr/ANConstraints.js +++ b/web/app/sketcher/constr/ANConstraints.js @@ -6,6 +6,8 @@ import {COS_FN, Polynomial, POW_1_FN, POW_2_FN, POW_3_FN, SIN_FN} from "./polyno import {Types} from "../io"; import Vector from "math/vector"; +import {cubicBezierDer2, cubicBezierPoint} from "../../brep/geom/curves/bezierCubic"; +import {greaterThanConstraint, lessThanConstraint} from "./barriers"; export const ConstraintDefinitions = { @@ -131,51 +133,107 @@ export const ConstraintDefinitions = { name: 'Point On Bezier Curve', defineParamsScope: ([pt, curve], callback) => { + const t = new Param(0.5, 't'); + t.constraints = [greaterThanConstraint(0), lessThanConstraint(1)]; curve.visitParams(callback); - callback(new Param(0.5, 't')); + callback(t); pt.visitParams(callback); }, collectPolynomials: (polynomials, [p0x,p0y, p3x,p3y, p1x,p1y, p2x,p2y, t, px, py]) => { - const bz3Poly = (p, t, p0, p1, p2, p3) => new Polynomial() - .monomial(-1) - .term(t, POW_3_FN) - .term(p0, POW_1_FN) - .monomial(3) - .term(t, POW_2_FN) - .term(p0, POW_1_FN) - .monomial(-3) - .term(t, POW_1_FN) - .term(p0, POW_1_FN) - .monomial(1) - .term(p0, POW_1_FN) + polynomials.push(bezier3Polynomial(px, t, p0x, p1x, p2x, p3x)); + polynomials.push(bezier3Polynomial(py, t, p0y, p1y, p2y, p3y)); + }, - .monomial(3) - .term(t, POW_3_FN) - .term(p1, POW_1_FN) + }, + + TangentLineBezier: { + id: 'TangentLineBezier', + name: 'Line & Bezier Tangency', + + defineParamsScope: ([segment, curve], callback) => { + const t0 = new Param(0.5, 't'); + t0.constraints = [greaterThanConstraint(0), lessThanConstraint(1)]; + const [p0, p1, p2, p3] = [curve.p0, curve.p1, curve.p2, curve.p3].map(p => p.toVectorArray()); + const [x0, y0] = cubicBezierPoint(p0, p1, p2, p3, t0.get()); + const [nx0, ny0] = cubicBezierDer2(p0, p1, p2, p3, t0.get()); + curve.visitParams(callback); + callback(t0); + callback(new Param(x0, 'X')); + callback(new Param(y0, 'Y')); + callback(new Param(nx0, 'X')); + callback(new Param(ny0, 'Y')); + callback(segment.params.ang); + segment.a.visitParams(callback); + }, + + collectPolynomials: (polynomials, [p0x,p0y, p3x,p3y, p1x,p1y, p2x,p2y, t, px,py, nx,ny, ang, ax,ay]) => { + polynomials.push(bezier3Polynomial(px, t, p0x, p1x, p2x, p3x)); + polynomials.push(bezier3Polynomial(py, t, p0y, p1y, p2y, p3y)); + //expanded second derivative: -6 P0 t + 6 P0 + 18 P1 t - 12 P1 - 18 P2 t + 6 P2 + 6 P3 t + const bzCubeD2 = (p, t, p0, p1, p2, p3) => new Polynomial() .monomial(-6) - .term(t, POW_2_FN) - .term(p1, POW_1_FN) - .monomial(3) + .term(p0, POW_1_FN) .term(t, POW_1_FN) + .monomial(6) + .term(p0, POW_1_FN) + .monomial(18) .term(p1, POW_1_FN) - - .monomial(-3) - .term(t, POW_3_FN) + .term(t, POW_1_FN) + .monomial(-12) + .term(p1, POW_1_FN) + .monomial(-18) .term(p2, POW_1_FN) - .monomial(3) - .term(t, POW_2_FN) + .term(t, POW_1_FN) + .monomial(6) .term(p2, POW_1_FN) - - .monomial(1) - .term(t, POW_3_FN) + .monomial(6) .term(p3, POW_1_FN) - - .monomial(-1) + .term(t, POW_1_FN) + .monomial(-1) .term(p, POW_1_FN); + //expanded first derivative: -3 P0 t^2 + 6 P0 t - 3 P0 + 9 P1 t^2 - 12 P1 t + 3 P1 - 9 P2 t^2 + 6 P2 t + 3 P3 t^2 + const bzCubeD1 = (p, t, p0, p1, p2, p3) => new Polynomial() + .monomial(-3) + .term(p0, POW_1_FN) + .term(t, POW_2_FN) + .monomial(6) + .term(p0, POW_1_FN) + .term(t, POW_1_FN) + .monomial(-3) + .term(p0, POW_1_FN) + .monomial(9) + .term(p1, POW_1_FN) + .term(t, POW_2_FN) + .monomial(-12) + .term(p1, POW_1_FN) + .term(t, POW_1_FN) + .monomial(3) + .term(p1, POW_1_FN) + .monomial(-9) + .term(p2, POW_1_FN) + .term(t, POW_2_FN) + .monomial(6) + .term(p2, POW_1_FN) + .term(t, POW_1_FN) + .monomial(3) + .term(p3, POW_1_FN) + .term(t, POW_2_FN) + .monomial(-1) + .term(p, POW_1_FN); - polynomials.push(bz3Poly(px, t, p0x, p1x, p2x, p3x)); - polynomials.push(bz3Poly(py, t, p0y, p1y, p2y, p3y)); + + polynomials.push(bzCubeD1(nx, t, p0x, p1x, p2x, p3x)); + polynomials.push(bzCubeD1(ny, t, p0y, p1y, p2y, p3y)); + polynomials.push(new Polynomial() + .monomial(-1) + .term(ny, POW_1_FN) + .term(ang, COS_FN) + .monomial() + .term(nx, POW_1_FN) + .term(ang, SIN_FN) + ); + ConstraintDefinitions.PointOnLine.collectPolynomials(polynomials, [px, py, ax, ay, ang]); }, }, @@ -743,6 +801,43 @@ function tangentLCPolynomial(ang, ax, ay, cx, cy, r, inverted) { .term(r, POW_1_FN); } +const bezier3Polynomial = (p, t, p0, p1, p2, p3) => new Polynomial() + .monomial(-1) + .term(t, POW_3_FN) + .term(p0, POW_1_FN) + .monomial(3) + .term(t, POW_2_FN) + .term(p0, POW_1_FN) + .monomial(-3) + .term(t, POW_1_FN) + .term(p0, POW_1_FN) + .monomial(1) + .term(p0, POW_1_FN) + + .monomial(3) + .term(t, POW_3_FN) + .term(p1, POW_1_FN) + .monomial(-6) + .term(t, POW_2_FN) + .term(p1, POW_1_FN) + .monomial(3) + .term(t, POW_1_FN) + .term(p1, POW_1_FN) + + .monomial(-3) + .term(t, POW_3_FN) + .term(p2, POW_1_FN) + .monomial(3) + .term(t, POW_2_FN) + .term(p2, POW_1_FN) + + .monomial(1) + .term(t, POW_3_FN) + .term(p3, POW_1_FN) + + .monomial(-1) + .term(p, POW_1_FN); + export class AlgNumConstraint { static Counter = 0; diff --git a/web/app/sketcher/constr/AlgNumSystem.js b/web/app/sketcher/constr/AlgNumSystem.js index 95a5ba1b..9b08c92d 100644 --- a/web/app/sketcher/constr/AlgNumSystem.js +++ b/web/app/sketcher/constr/AlgNumSystem.js @@ -3,7 +3,7 @@ import {eqEps} from "../../brep/geom/tolerance"; import {Polynomial, POW_1_FN} from "./polynomial"; import {compositeFn} from "gems/func"; -const DEBUG = false; +const DEBUG = true; export class AlgNumSubSystem { @@ -472,17 +472,20 @@ class Isolation { } this.dof = this.beingSolvedParams.size - polynomials.length; - let penaltyFunction = new PolynomialResidual(); this.beingSolvedParams.forEach(sp => { const param = sp.objectParam; if (param.constraints) { - param.constraints.forEach(pc => penaltyFunction.add(sp, pc)) + param.constraints.forEach(pc => { + let penaltyFunction = new PolynomialResidual(); + penaltyFunction.add(sp, pc); + residuals.push(penaltyFunction); + }) } }); - if (penaltyFunction.params.length) { - // residuals.push(penaltyFunction); - } + // if (penaltyFunction.params.length) { + // residuals.push(penaltyFunction); + // } this.numericalSolver = prepare(residuals); } diff --git a/web/app/sketcher/shapes/arc.js b/web/app/sketcher/shapes/arc.js index 8d90d6ad..12add096 100644 --- a/web/app/sketcher/shapes/arc.js +++ b/web/app/sketcher/shapes/arc.js @@ -2,8 +2,6 @@ import * as math from '../../math/math'; import Vector from 'math/vector'; import {SketchObject} from './sketch-object'; import {Param} from "./param"; -import {greaterThanConstraint} from "../constr/barriers"; -import {MIN_RADIUS} from "./circle"; import {AlgNumConstraint, ConstraintDefinitions} from "../constr/ANConstraints"; import {makeAngle0_360} from "../../math/math"; @@ -20,7 +18,6 @@ export class Arc extends SketchObject { this.children.push(a, b, c); this.r = new Param(0, 'R'); - this.r.constraints = [greaterThanConstraint(MIN_RADIUS)]; this.r.enforceVisualLimit = true; this.ang1 = new Param(0, 'A'); diff --git a/web/app/sketcher/shapes/bezier-curve.js b/web/app/sketcher/shapes/bezier-curve.js index 7f4514e7..f3d5ceea 100644 --- a/web/app/sketcher/shapes/bezier-curve.js +++ b/web/app/sketcher/shapes/bezier-curve.js @@ -23,6 +23,19 @@ export class BezierCurve extends SketchObject { } } + get p0() { + return this.a; + } + get p1() { + return this.cp1; + } + get p2() { + return this.cp2; + } + get p3() { + return this.b; + } + stabilize(viewer) { this.children.forEach(c => c.stabilize(viewer)); } diff --git a/web/app/sketcher/shapes/circle.js b/web/app/sketcher/shapes/circle.js index 0f2ab71c..b0742cb9 100644 --- a/web/app/sketcher/shapes/circle.js +++ b/web/app/sketcher/shapes/circle.js @@ -1,7 +1,6 @@ import * as math from '../../math/math'; import {SketchObject} from './sketch-object' import {Param} from "./param"; -import {greaterThanConstraint} from "../constr/barriers"; export const MIN_RADIUS = 100; @@ -13,7 +12,6 @@ export class Circle extends SketchObject { c.parent = this; this.children.push(c); this.r = new Param(0, 'R'); - this.r.constraints = [greaterThanConstraint(MIN_RADIUS)]; this.r.enforceVisualLimit = true; } diff --git a/web/app/sketcher/shapes/point.js b/web/app/sketcher/shapes/point.js index ba840292..3bcb5f93 100644 --- a/web/app/sketcher/shapes/point.js +++ b/web/app/sketcher/shapes/point.js @@ -76,6 +76,10 @@ export class EndPoint extends SketchObject { this.setXY(arr[0], arr[1]); } + toVectorArray() { + return [this.x, this.y]; + } + toVector() { return new Vector(this.x, this.y); }