signed perpendicular constraint and fillet based on it

This commit is contained in:
Val Erastov (xibyte) 2019-12-02 12:12:30 -08:00
parent c6ceb723fe
commit c559b4e125
4 changed files with 117 additions and 15 deletions

View file

@ -17,6 +17,8 @@ function createByConstraintName(name, params, values) {
return new Perpendicular(params);
case "parallel":
return new Parallel(params);
case "signedPerpendicular":
return new SignedPerpendicular(params);
case "P2LDistanceSigned":
return new P2LDistanceSigned(params, values[0]);
case "P2LDistance":
@ -409,6 +411,77 @@ function P2PDistanceV(params) {
}
}
function SignedPerpendicular(params) {
this.params = params;
const X1 = 0;
const Y1 = 1;
const X2 = 2;
const Y2 = 3;
const X3 = 4;
const Y3 = 5;
const X4 = 6;
const Y4 = 7;
this.error = function() {
let x1 = params[X1].get();
let x2 = params[X2].get();
let y1 = params[Y1].get();
let y2 = params[Y2].get();
let x3 = params[X3].get();
let x4 = params[X4].get();
let y4 = params[Y4].get();
let y3 = params[Y3].get();
const dx1 = y1 - y2;
const dy1 = x2 - x1;
const dx2 = x4 - x3;
const dy2 = y4 - y3;
let c1 = Math.sqrt(sq(dx1) + sq(dy1));
let c2 = Math.sqrt(sq(dx2) + sq(dy2));
return dx1*dx2 + dy1*dy2 - c1 * c2;
};
//d(((x-a) * (b - c))^2 ) / dx
this.gradient = function (out) {
let x1 = params[X1].get();
let x2 = params[X2].get();
let y1 = params[Y1].get();
let y2 = params[Y2].get();
let x3 = params[X3].get();
let x4 = params[X4].get();
let y3 = params[Y3].get();
let y4 = params[Y4].get();
let dx1 = y1 - y2;
let dy1 = x2 - x1;
let dx2 = x4 - x3;
let dy2 = y4 - y3;
let c1 = Math.max(Math.sqrt(sq(dx1) + sq(dy1)), 0.001);
let c2 = Math.max(Math.sqrt(sq(dx2) + sq(dy2)), 0.001);
out[X1] = y3 - y4 + (c2 * (x2 - x1)) / c1;
out[X2] = y4 - y3 - (c2 * (x2 - x1)) / c1;
out[Y1] = x4 - x3 - (c2 * (y1 - y2)) / c1;
out[Y2] = x3 - x4 + (c2 * (y1 - y2)) / c1;
out[X3] = y2 - y1 + (c1 * (x4 - x3)) / c2;
out[X4] = y1 - y2 - (c1 * (x4 - x3)) / c2;
out[Y3] = x1 - x2 + (c1 * (y4 - y3)) / c2;
out[Y4] = x2 - x1 - (c1 * (y4 - y3)) / c2;
}
this.gradient = NumericGradient;
}
function Parallel(params) {
this.params = params;

View file

@ -560,6 +560,44 @@ Constraints.Tangent.prototype.getObjects = function() {
return [this.arc, this.line];
};
// ------------------------------------------------------------------------------------------------------------------ //
export class SignedPerpendicular extends AbstractConstraint {
static deserialize(refs, data) {
return new SignedPerpendicular(refs(data[0]), refs(data[1]), refs(data[2]), refs(data[3]));
};
constructor(p1, p2, p3, p4) {
super();
this.points = [p1, p2, p3, p4];
};
getSolveData() {
const params = [];
this.points.forEach(p => p.collectParams(params));
return [['signedPerpendicular', params, []]];
}
serialize() {
return [this.NAME, this.points.map(p => p.id)];
}
getObjects() {
const collector = new Constraints.ParentsCollector();
this.points.forEach(p => collector.check(p));
return collector.parents;
}
}
Constraints.SignedPerpendicular = SignedPerpendicular;
Constraints.SignedPerpendicular.prototype.NAME = 'SignedPerpendicular';
Constraints.SignedPerpendicular.prototype.UI_NAME = 'SignedPerpendicular';
Constraints.Factory[SignedPerpendicular.prototype.NAME] = Coincident.deserialize;
// ------------------------------------------------------------------------------------------------------------------ //
/** @constructor */
@ -1023,9 +1061,13 @@ Constraints.Fillet = function(point1, point2, arc) {
this.point1 = point1;
this.point2 = point2;
this.arc = arc;
const line1 = point1.parent;
const line2 = point2.parent;
this.contraints = [
new Constraints.Tangent( arc, point1.parent),
new Constraints.Tangent( arc, point2.parent),
new Constraints.SignedPerpendicular( arc.a, arc.c, point1, line1.opposite(point1)),
new Constraints.SignedPerpendicular( arc.b, arc.c, line2.opposite(point2), point2),
new Constraints.Coincident( arc.a, point1),
new Constraints.Coincident( arc.b, point2)
];

View file

@ -69,18 +69,6 @@ export class FilletTool extends Tool {
arc.stabilize(this.viewer);
pm._add(new Constraints.Fillet( point1, point2, arc));
this.viewer.validators.push(() => {
function validOn(p, left) {
let op = p.parent.opposite(p);
let opV = op.toVector();
let dir = p.toVector()._minus(opV)._normalize();
let centerDir = arc.c.toVector()._minus(opV)._normalize();
let z = centerDir.cross(dir).z;
return left ? z < 0.1 : z > -0.1;
}
return validOn(point1, true) && validOn(point2, false);
});
//function otherEnd(point) {
// if (point.parent.a.id === point.id) {
// return point.parent.b;

View file

@ -86,7 +86,6 @@ class Viewer {
this.historyManager = new HistoryManager(this);
this.transformation = null;
this.screenToModelMatrix = null;
this.validators = [];
this.refresh();
}