mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-21 16:05:44 +01:00
signed perpendicular constraint and fillet based on it
This commit is contained in:
parent
c6ceb723fe
commit
c559b4e125
4 changed files with 117 additions and 15 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
];
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -86,7 +86,6 @@ class Viewer {
|
|||
this.historyManager = new HistoryManager(this);
|
||||
this.transformation = null;
|
||||
this.screenToModelMatrix = null;
|
||||
this.validators = [];
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue