mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-08 01:13:27 +01:00
ellipse tangent UI support
This commit is contained in:
parent
8a9050d1ed
commit
e01b450ad2
6 changed files with 105 additions and 24 deletions
|
|
@ -111,7 +111,6 @@ IO.prototype._loadSketch = function(sketch) {
|
||||||
const b = endPoint(points[1]);
|
const b = endPoint(points[1]);
|
||||||
const c = endPoint(points[2]);
|
const c = endPoint(points[2]);
|
||||||
skobj = new Arc(a, b, c);
|
skobj = new Arc(a, b, c);
|
||||||
if (!aux) skobj.stabilize(this.viewer);
|
|
||||||
} else if (_class === T.CIRCLE) {
|
} else if (_class === T.CIRCLE) {
|
||||||
const c = endPoint(obj['c']);
|
const c = endPoint(obj['c']);
|
||||||
skobj = new Circle(c);
|
skobj = new Circle(c);
|
||||||
|
|
@ -134,6 +133,7 @@ IO.prototype._loadSketch = function(sketch) {
|
||||||
skobj = new DiameterDimension(obj['obj']);
|
skobj = new DiameterDimension(obj['obj']);
|
||||||
}
|
}
|
||||||
if (skobj != null) {
|
if (skobj != null) {
|
||||||
|
if (!aux) skobj.stabilize(this.viewer);
|
||||||
if (aux) skobj.accept(function(o){o.aux = true; return true;});
|
if (aux) skobj.accept(function(o){o.aux = true; return true;});
|
||||||
if (obj['edge'] !== undefined) {
|
if (obj['edge'] !== undefined) {
|
||||||
skobj.edge = obj['edge'];
|
skobj.edge = obj['edge'];
|
||||||
|
|
|
||||||
|
|
@ -267,10 +267,14 @@ ParametricManager.prototype.lockConvex = function(objs, warnCallback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
ParametricManager.prototype.tangent = function(objs) {
|
ParametricManager.prototype.tangent = function(objs) {
|
||||||
var al = fetch.arcCircAndLine(objs);
|
const ellipses = fetch.generic(objs, ['TCAD.TWO.Ellipse'], 0);
|
||||||
var arc = al[0];
|
const lines = fetch.generic(objs, ['TCAD.TWO.Segment'], 1);
|
||||||
var line = al[1];
|
if (ellipses.length > 0) {
|
||||||
this.add(new Constraints.Tangent( arc, line));
|
this.add(new Constraints.EllipseTangent(lines[0], ellipses[0]));
|
||||||
|
} else {
|
||||||
|
const arcs = fetch.generic(objs, ['TCAD.TWO.Arc', 'TCAD.TWO.Circle'], 1);
|
||||||
|
this.add(new Constraints.Tangent(arcs[0], lines[0]));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ParametricManager.prototype.rr = function(arcs) {
|
ParametricManager.prototype.rr = function(arcs) {
|
||||||
|
|
@ -1104,6 +1108,22 @@ Constraints.P2PDistanceV.prototype.getSolveData = function() {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------------------------ //
|
// ------------------------------------------------------------------------------------------------------------------ //
|
||||||
|
|
||||||
|
/** @constructor */
|
||||||
|
Constraints.GreaterThan = function(p, limit) {
|
||||||
|
this.p = p;
|
||||||
|
this.limit = limit;
|
||||||
|
};
|
||||||
|
|
||||||
|
Constraints.GreaterThan.prototype.aux = true;
|
||||||
|
Constraints.GreaterThan.prototype.NAME = 'GreaterThan';
|
||||||
|
Constraints.GreaterThan.prototype.UI_NAME = 'Greater Than';
|
||||||
|
|
||||||
|
Constraints.GreaterThan.prototype.getSolveData = function() {
|
||||||
|
return [[this.NAME, [this.p], [this.limit]]];
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------------------------ //
|
||||||
|
|
||||||
/** @constructor */
|
/** @constructor */
|
||||||
Constraints.Radius = function(arc, d) {
|
Constraints.Radius = function(arc, d) {
|
||||||
this.arc = arc;
|
this.arc = arc;
|
||||||
|
|
@ -1392,6 +1412,39 @@ Constraints.PointOnEllipse.prototype.getObjects = function() {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------------------------ //
|
// ------------------------------------------------------------------------------------------------------------------ //
|
||||||
|
|
||||||
|
/** @constructor */
|
||||||
|
Constraints.EllipseTangent = function(line, ellipse) {
|
||||||
|
this.line = line;
|
||||||
|
this.ellipse = ellipse;
|
||||||
|
};
|
||||||
|
|
||||||
|
Constraints.EllipseTangent.prototype.NAME = 'EllipseTangent';
|
||||||
|
Constraints.EllipseTangent.prototype.UI_NAME = 'Tangent Ellipse';
|
||||||
|
|
||||||
|
Constraints.EllipseTangent.prototype.getSolveData = function() {
|
||||||
|
const params = [];
|
||||||
|
this.line.collectParams(params);
|
||||||
|
this.ellipse.ep1.collectParams(params);
|
||||||
|
this.ellipse.ep2.collectParams(params);
|
||||||
|
params.push(this.ellipse.r);
|
||||||
|
return [['EllipseTangent', params, []]];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Constraints.EllipseTangent.prototype.serialize = function() {
|
||||||
|
return [this.NAME, [this.line.id, this.ellipse.id]];
|
||||||
|
};
|
||||||
|
|
||||||
|
Constraints.Factory[Constraints.EllipseTangent.prototype.NAME] = function(refs, data) {
|
||||||
|
return new Constraints.EllipseTangent(refs(data[0]), refs(data[1]));
|
||||||
|
};
|
||||||
|
|
||||||
|
Constraints.EllipseTangent.prototype.getObjects = function() {
|
||||||
|
return [this.line, this.ellipse];
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------------------------ //
|
||||||
|
|
||||||
/** @constructor */
|
/** @constructor */
|
||||||
Constraints.PointInMiddle = function(point, line) {
|
Constraints.PointInMiddle = function(point, line) {
|
||||||
this.point = point;
|
this.point = point;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import {Ref} from './ref'
|
import {Ref} from './ref'
|
||||||
import {SketchObject} from './sketch-object'
|
import {SketchObject} from './sketch-object'
|
||||||
import {EllipseTool, STATE_RADIUS} from '../tools/ellipse'
|
import {EllipseTool, STATE_RADIUS} from '../tools/ellipse'
|
||||||
|
import {Constraints} from '../parametric'
|
||||||
|
|
||||||
import * as math from '../../math/math';
|
import * as math from '../../math/math';
|
||||||
|
|
||||||
|
|
@ -13,10 +14,31 @@ export class Ellipse extends SketchObject {
|
||||||
this.addChild(this.ep1);
|
this.addChild(this.ep1);
|
||||||
this.addChild(this.ep2);
|
this.addChild(this.ep2);
|
||||||
this.r = new Ref(0);
|
this.r = new Ref(0);
|
||||||
this.r.value = this.radiusX * 0.5;
|
this.r.set(this.radiusX * 0.5);
|
||||||
this.r.obj = this;
|
this.r.obj = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recoverIfNecessary() {
|
||||||
|
let recovered = false;
|
||||||
|
if (math.distanceAB(this.ep1, this.ep2) <= math.TOLERANCE) {
|
||||||
|
this.ep1.translate(-RECOVER_LENGTH, -RECOVER_LENGTH);
|
||||||
|
this.ep2.translate(RECOVER_LENGTH, RECOVER_LENGTH);
|
||||||
|
recovered = true;
|
||||||
|
}
|
||||||
|
if (this.radiusY <= 0.1) {
|
||||||
|
this.r.set(RECOVER_LENGTH);
|
||||||
|
recovered = true;
|
||||||
|
}
|
||||||
|
return recovered;
|
||||||
|
}
|
||||||
|
|
||||||
|
collectParams(params) {
|
||||||
|
this.ep1.collectParams(params);
|
||||||
|
this.ep2.collectParams(params);
|
||||||
|
params.push(this.r);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
get rotation() {
|
get rotation() {
|
||||||
return Math.atan2(this.ep2.y - this.ep1.y, this.ep2.x - this.ep1.x);
|
return Math.atan2(this.ep2.y - this.ep1.y, this.ep2.x - this.ep1.x);
|
||||||
}
|
}
|
||||||
|
|
@ -39,7 +61,9 @@ export class Ellipse extends SketchObject {
|
||||||
|
|
||||||
drawImpl(ctx, scale) {
|
drawImpl(ctx, scale) {
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.ellipse(this.centerX, this.centerY, this.radiusX, this.radiusY, this.rotation, 0, 2 * Math.PI);
|
const radiusX = Math.max(this.radiusX, 1e-8);
|
||||||
|
const radiusY = Math.max(this.radiusY, 1e-8);
|
||||||
|
ctx.ellipse(this.centerX, this.centerY, radiusX, radiusY, this.rotation, 0, 2 * Math.PI);
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,4 +104,5 @@ export class Ellipse extends SketchObject {
|
||||||
}
|
}
|
||||||
Ellipse.prototype._class = 'TCAD.TWO.Ellipse';
|
Ellipse.prototype._class = 'TCAD.TWO.Ellipse';
|
||||||
|
|
||||||
const sq = (a) => a * a;
|
const sq = (a) => a * a;
|
||||||
|
const RECOVER_LENGTH = 100;
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import {SketchObject} from './sketch-object'
|
import {SketchObject} from './sketch-object'
|
||||||
import Vector from '../../math/vector'
|
import Vector from '../../math/vector'
|
||||||
|
import {Constraints} from '../parametric'
|
||||||
import * as math from '../../math/math'
|
import * as math from '../../math/math'
|
||||||
|
|
||||||
export class Segment extends SketchObject {
|
export class Segment extends SketchObject {
|
||||||
|
|
@ -13,14 +14,15 @@ export class Segment extends SketchObject {
|
||||||
this.children.push(a, b);
|
this.children.push(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
validate() {
|
recoverIfNecessary() {
|
||||||
return math.distanceAB(this.a, this.b) > math.TOLERANCE;
|
if (math.distanceAB(this.a, this.b) > math.TOLERANCE) {
|
||||||
}
|
return false;
|
||||||
|
} else {
|
||||||
recover() {
|
const recoverLength = 100;
|
||||||
var recoverLength = 100;
|
this.a.translate(-recoverLength, -recoverLength);
|
||||||
this.a.translate(-recoverLength, -recoverLength);
|
this.b.translate( recoverLength, recoverLength);
|
||||||
this.b.translate( recoverLength, recoverLength);
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
collectParams(params) {
|
collectParams(params) {
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,12 @@ export class SketchObject {
|
||||||
}
|
}
|
||||||
return visitor(this);
|
return visitor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
validate() {
|
stabilize(viewer) {
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
recover() {
|
recoverIfNecessary() {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
getDefaultTool(viewer) {
|
getDefaultTool(viewer) {
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,10 @@ export class DragTool extends Tool {
|
||||||
|
|
||||||
var paramsToUpdate = [];
|
var paramsToUpdate = [];
|
||||||
this.viewer.accept(function (obj) {
|
this.viewer.accept(function (obj) {
|
||||||
if (!obj.validate() && obj.aux !== true) {
|
if (obj.aux !== true) {
|
||||||
obj.recover();
|
if (obj.recoverIfNecessary()){
|
||||||
obj.collectParams(paramsToUpdate);
|
obj.collectParams(paramsToUpdate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue