mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-08 01:13:27 +01:00
point on ellipse constraint
This commit is contained in:
parent
441bed2639
commit
5761164b0c
2 changed files with 96 additions and 1 deletions
|
|
@ -23,6 +23,8 @@ function createByConstraintName(name, params, values) {
|
||||||
return new P2PDistance(params, values[0]);
|
return new P2PDistance(params, values[0]);
|
||||||
case "P2PDistanceV":
|
case "P2PDistanceV":
|
||||||
return new P2PDistanceV(params);
|
return new P2PDistanceV(params);
|
||||||
|
case "PointOnEllipse":
|
||||||
|
return new PointOnEllipse(params);
|
||||||
case "angle":
|
case "angle":
|
||||||
return new Angle(params);
|
return new Angle(params);
|
||||||
case "angleConst":
|
case "angleConst":
|
||||||
|
|
@ -367,7 +369,6 @@ function P2PDistanceV(params) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** @constructor */
|
/** @constructor */
|
||||||
function Parallel(params) {
|
function Parallel(params) {
|
||||||
|
|
||||||
|
|
@ -499,6 +500,62 @@ function Angle(params) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @constructor */
|
||||||
|
function PointOnEllipse(params) {
|
||||||
|
|
||||||
|
this.params = params;
|
||||||
|
|
||||||
|
const PX = 0;
|
||||||
|
const PY = 1;
|
||||||
|
const EP1X = 2;
|
||||||
|
const EP1Y = 3;
|
||||||
|
const EP2X = 4;
|
||||||
|
const EP2Y = 5;
|
||||||
|
const R = 6;
|
||||||
|
|
||||||
|
this.error = function() {
|
||||||
|
const sq = x => x * x;
|
||||||
|
const px = params[PX].get();
|
||||||
|
const py = params[PY].get();
|
||||||
|
const ep1x = params[EP1X].get();
|
||||||
|
const ep1y = params[EP1Y].get();
|
||||||
|
const ep2x = params[EP2X].get();
|
||||||
|
const ep2y = params[EP2Y].get();
|
||||||
|
const radiusY = params[R].get();
|
||||||
|
|
||||||
|
const centerX = ep1x + (ep2x - ep1x) * 0.5;
|
||||||
|
const centerY = ep1y + (ep2y - ep1y) * 0.5;
|
||||||
|
const rotation = Math.atan2(ep2y - ep1y, ep2x - ep1x);
|
||||||
|
let x = px - centerX;
|
||||||
|
let y = py - centerY;
|
||||||
|
const polarAngle = Math.atan2(y, x) - rotation;
|
||||||
|
const polarRadius = Math.sqrt(x*x + y*y);
|
||||||
|
const radiusX = Math.sqrt(sq(ep1x - ep2x) + sq(ep1y - ep2y)) * 0.5;
|
||||||
|
|
||||||
|
const L = Math.sqrt(1/( sq(Math.cos(polarAngle)/radiusX) + sq(Math.sin(polarAngle)/radiusY)));
|
||||||
|
return L - polarRadius
|
||||||
|
};
|
||||||
|
|
||||||
|
this.gradient = function(out) {
|
||||||
|
const h = 1;
|
||||||
|
const approx = (param) => {
|
||||||
|
const fx = this.error();
|
||||||
|
params[param].set(params[param].get() + h);
|
||||||
|
const fhx = this.error();
|
||||||
|
params[param].set(params[param].get() - h);
|
||||||
|
return (fhx - fx) / h;
|
||||||
|
};
|
||||||
|
|
||||||
|
out[PX] = approx(PX);
|
||||||
|
out[PY] = approx(PY);
|
||||||
|
out[EP1X] = approx(EP1X);
|
||||||
|
out[EP1Y] = approx(EP1Y);
|
||||||
|
out[EP2X] = approx(EP2X);
|
||||||
|
out[EP2Y] = approx(EP2Y);
|
||||||
|
out[R] = approx(R);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function _fixNaN(grad) {
|
function _fixNaN(grad) {
|
||||||
for (var i = 0; i < grad.length; i++) {
|
for (var i = 0; i < grad.length; i++) {
|
||||||
if (isNaN(grad[i])) {
|
if (isNaN(grad[i])) {
|
||||||
|
|
|
||||||
|
|
@ -331,6 +331,12 @@ ParametricManager.prototype.pointOnArc = function(objs) {
|
||||||
this.add(new Constraints.PointOnArc(points[0], arcs[0]));
|
this.add(new Constraints.PointOnArc(points[0], arcs[0]));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ParametricManager.prototype.pointOnEllipse = function(objs) {
|
||||||
|
const points = fetch.generic(objs, ['TCAD.TWO.EndPoint'], 1);
|
||||||
|
const ellipses = fetch.generic(objs, ['TCAD.TWO.Ellipse'], 1);
|
||||||
|
this.add(new Constraints.PointOnEllipse(points[0], ellipses[0]));
|
||||||
|
};
|
||||||
|
|
||||||
ParametricManager.prototype.pointOnLine = function(objs) {
|
ParametricManager.prototype.pointOnLine = function(objs) {
|
||||||
var pl = fetch.pointAndLine(objs);
|
var pl = fetch.pointAndLine(objs);
|
||||||
var target = pl[0];
|
var target = pl[0];
|
||||||
|
|
@ -1340,6 +1346,38 @@ Constraints.PointOnArc.prototype.getObjects = function() {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------------------------ //
|
// ------------------------------------------------------------------------------------------------------------------ //
|
||||||
|
|
||||||
|
/** @constructor */
|
||||||
|
Constraints.PointOnEllipse = function(point, ellipse) {
|
||||||
|
this.point = point;
|
||||||
|
this.ellipse= ellipse;
|
||||||
|
};
|
||||||
|
|
||||||
|
Constraints.PointOnEllipse.prototype.NAME = 'PointOnEllipse';
|
||||||
|
Constraints.PointOnEllipse.prototype.UI_NAME = 'Point On Ellipse';
|
||||||
|
|
||||||
|
Constraints.PointOnEllipse.prototype.getSolveData = function() {
|
||||||
|
var params = [];
|
||||||
|
this.point.collectParams(params);
|
||||||
|
this.ellipse.ep1.collectParams(params);
|
||||||
|
this.ellipse.ep2.collectParams(params);
|
||||||
|
params.push(this.ellipse.r);
|
||||||
|
return [['PointOnEllipse', params, []]];
|
||||||
|
};
|
||||||
|
|
||||||
|
Constraints.PointOnEllipse.prototype.serialize = function() {
|
||||||
|
return [this.NAME, [this.point.id, this.ellipse.id]];
|
||||||
|
};
|
||||||
|
|
||||||
|
Constraints.Factory[Constraints.PointOnEllipse.prototype.NAME] = function(refs, data) {
|
||||||
|
return new Constraints.PointOnEllipse(refs(data[0]), refs(data[1]));
|
||||||
|
};
|
||||||
|
|
||||||
|
Constraints.PointOnEllipse.prototype.getObjects = function() {
|
||||||
|
return [this.point, this.ellipse];
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------------------------ //
|
||||||
|
|
||||||
/** @constructor */
|
/** @constructor */
|
||||||
Constraints.PointInMiddle = function(point, line) {
|
Constraints.PointInMiddle = function(point, line) {
|
||||||
this.point = point;
|
this.point = point;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue