mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-26 02:12:28 +01:00
bezier curve tangent constraint
This commit is contained in:
parent
b1aabfed5c
commit
8254f3dbbb
8 changed files with 160 additions and 47 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue