mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-07 17:04:58 +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 c = endPoint(points[2]);
|
||||
skobj = new Arc(a, b, c);
|
||||
if (!aux) skobj.stabilize(this.viewer);
|
||||
} else if (_class === T.CIRCLE) {
|
||||
const c = endPoint(obj['c']);
|
||||
skobj = new Circle(c);
|
||||
|
|
@ -134,6 +133,7 @@ IO.prototype._loadSketch = function(sketch) {
|
|||
skobj = new DiameterDimension(obj['obj']);
|
||||
}
|
||||
if (skobj != null) {
|
||||
if (!aux) skobj.stabilize(this.viewer);
|
||||
if (aux) skobj.accept(function(o){o.aux = true; return true;});
|
||||
if (obj['edge'] !== undefined) {
|
||||
skobj.edge = obj['edge'];
|
||||
|
|
|
|||
|
|
@ -267,10 +267,14 @@ ParametricManager.prototype.lockConvex = function(objs, warnCallback) {
|
|||
};
|
||||
|
||||
ParametricManager.prototype.tangent = function(objs) {
|
||||
var al = fetch.arcCircAndLine(objs);
|
||||
var arc = al[0];
|
||||
var line = al[1];
|
||||
this.add(new Constraints.Tangent( arc, line));
|
||||
const ellipses = fetch.generic(objs, ['TCAD.TWO.Ellipse'], 0);
|
||||
const lines = fetch.generic(objs, ['TCAD.TWO.Segment'], 1);
|
||||
if (ellipses.length > 0) {
|
||||
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) {
|
||||
|
|
@ -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 */
|
||||
Constraints.Radius = function(arc, d) {
|
||||
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 */
|
||||
Constraints.PointInMiddle = function(point, line) {
|
||||
this.point = point;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import {Ref} from './ref'
|
||||
import {SketchObject} from './sketch-object'
|
||||
import {EllipseTool, STATE_RADIUS} from '../tools/ellipse'
|
||||
import {Constraints} from '../parametric'
|
||||
|
||||
import * as math from '../../math/math';
|
||||
|
||||
|
|
@ -13,10 +14,31 @@ export class Ellipse extends SketchObject {
|
|||
this.addChild(this.ep1);
|
||||
this.addChild(this.ep2);
|
||||
this.r = new Ref(0);
|
||||
this.r.value = this.radiusX * 0.5;
|
||||
this.r.set(this.radiusX * 0.5);
|
||||
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() {
|
||||
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) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
@ -80,4 +104,5 @@ export class Ellipse extends SketchObject {
|
|||
}
|
||||
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 Vector from '../../math/vector'
|
||||
import {Constraints} from '../parametric'
|
||||
import * as math from '../../math/math'
|
||||
|
||||
export class Segment extends SketchObject {
|
||||
|
|
@ -13,14 +14,15 @@ export class Segment extends SketchObject {
|
|||
this.children.push(a, b);
|
||||
}
|
||||
|
||||
validate() {
|
||||
return math.distanceAB(this.a, this.b) > math.TOLERANCE;
|
||||
}
|
||||
|
||||
recover() {
|
||||
var recoverLength = 100;
|
||||
this.a.translate(-recoverLength, -recoverLength);
|
||||
this.b.translate( recoverLength, recoverLength);
|
||||
recoverIfNecessary() {
|
||||
if (math.distanceAB(this.a, this.b) > math.TOLERANCE) {
|
||||
return false;
|
||||
} else {
|
||||
const recoverLength = 100;
|
||||
this.a.translate(-recoverLength, -recoverLength);
|
||||
this.b.translate( recoverLength, recoverLength);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
collectParams(params) {
|
||||
|
|
|
|||
|
|
@ -31,12 +31,12 @@ export class SketchObject {
|
|||
}
|
||||
return visitor(this);
|
||||
}
|
||||
|
||||
validate() {
|
||||
return true;
|
||||
|
||||
stabilize(viewer) {
|
||||
}
|
||||
|
||||
recover() {
|
||||
|
||||
recoverIfNecessary() {
|
||||
return false;
|
||||
}
|
||||
|
||||
getDefaultTool(viewer) {
|
||||
|
|
|
|||
|
|
@ -59,9 +59,10 @@ export class DragTool extends Tool {
|
|||
|
||||
var paramsToUpdate = [];
|
||||
this.viewer.accept(function (obj) {
|
||||
if (!obj.validate() && obj.aux !== true) {
|
||||
obj.recover();
|
||||
obj.collectParams(paramsToUpdate);
|
||||
if (obj.aux !== true) {
|
||||
if (obj.recoverIfNecessary()){
|
||||
obj.collectParams(paramsToUpdate);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue