mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-10 02:13:58 +01:00
convex constraint
This commit is contained in:
parent
2471272ee4
commit
17b7c8bade
5 changed files with 257 additions and 20 deletions
|
|
@ -26,6 +26,8 @@ TCAD.constraints.create = function(name, params, values) {
|
|||
var _ = true, x = false;
|
||||
// Exclude angle value from parameters
|
||||
return new TCAD.constraints.ConstantWrapper(new TCAD.constraints.Angle(params), [x,x,x,x,x,x,x,x,_]);
|
||||
case 'LockConvex':
|
||||
return new TCAD.constraints.LockConvex(params);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -82,6 +84,47 @@ TCAD.constraints.MinLength = function(params, distance) {
|
|||
}
|
||||
};
|
||||
|
||||
TCAD.constraints.LockConvex = function(params) {
|
||||
this.params = params;
|
||||
|
||||
var _pcx = 0;
|
||||
var _pcy = 1;
|
||||
var _pax = 2;
|
||||
var _pay = 3;
|
||||
var _ptx = 4;
|
||||
var _pty = 5;
|
||||
|
||||
this.error = function() {
|
||||
var cx = params[_pcx].get();
|
||||
var cy = params[_pcy].get();
|
||||
var ax = params[_pax].get();
|
||||
var ay = params[_pay].get();
|
||||
var tx = params[_ptx].get();
|
||||
var ty = params[_pty].get();
|
||||
|
||||
var crossProductNorm = (cx - ax) * (ty - ay) - (cy - ay) * (tx - ax);
|
||||
|
||||
var violate = crossProductNorm < 0;
|
||||
return violate ? crossProductNorm : 0;
|
||||
};
|
||||
|
||||
this.gradient = function(out) {
|
||||
var cx = params[_pcx].get();
|
||||
var cy = params[_pcy].get();
|
||||
var ax = params[_pax].get();
|
||||
var ay = params[_pay].get();
|
||||
var tx = params[_ptx].get();
|
||||
var ty = params[_pty].get();
|
||||
|
||||
out[_pcx] = ty-ay;
|
||||
out[_pcy] = ax-tx;
|
||||
out[_pax] = cy-ty;
|
||||
out[_pay] = tx-cx;
|
||||
out[_ptx] = ay-cy;
|
||||
out[_pty] = cx-ax;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @constructor */
|
||||
TCAD.constraints.ConstantWrapper = function(constr, mask) {
|
||||
|
|
|
|||
|
|
@ -193,6 +193,9 @@ TCAD.App2D = function() {
|
|||
this.registerAction('symmetry', "Symmetry", function () {
|
||||
app.viewer.parametricManager.symmetry(app.viewer.selected, prompt);
|
||||
});
|
||||
this.registerAction('lockConvex', "Lock Convexity", function () {
|
||||
app.viewer.parametricManager.lockConvex(app.viewer.selected, alert);
|
||||
});
|
||||
|
||||
this.registerAction('analyzeConstraint', "Analyze Constraint", function () {
|
||||
app.viewer.parametricManager.analyze(alert);
|
||||
|
|
|
|||
|
|
@ -167,6 +167,56 @@ TCAD.TWO.ParametricManager.prototype.perpendicular = function(objs) {
|
|||
this.add(new TCAD.TWO.Constraints.Perpendicular(lines[0], lines[1]));
|
||||
};
|
||||
|
||||
TCAD.TWO.ParametricManager.prototype.lockConvex = function(objs, warnCallback) {
|
||||
var lines = this._fetchTwoLines(objs);
|
||||
var l1 = lines[0];
|
||||
var l2 = lines[1];
|
||||
var pts =[l1.a, l1.b, l2.a, l2.b];
|
||||
function isLinked(p1, p2) {
|
||||
for (var i = 0; i < p1.linked.length; ++i) {
|
||||
if (p1.linked[i].id === p2.id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function swap(arr, i1, i2) {
|
||||
var _ = arr[i1];
|
||||
arr[i1] = arr[i2];
|
||||
arr[i2] = _;
|
||||
}
|
||||
|
||||
if (isLinked(pts[0], pts[2])) {
|
||||
swap(pts, 0, 1);
|
||||
} else if (isLinked(pts[0], pts[3])) {
|
||||
swap(pts, 0, 1);
|
||||
swap(pts, 2, 3);
|
||||
} else if (isLinked(pts[1], pts[3])) {
|
||||
swap(pts, 2, 3);
|
||||
} else if (isLinked(pts[1], pts[2])) {
|
||||
//we are good
|
||||
} else {
|
||||
warnCallback("Lines must be connected");
|
||||
return;
|
||||
}
|
||||
|
||||
var c = pts[0];
|
||||
var a = pts[1];
|
||||
var t = pts[3];
|
||||
|
||||
// ||ac x at|| > 0
|
||||
var crossNorma = (c.x - a.x) * (t.y - a.y) - (c.y - a.y) * (t.x - a.x);
|
||||
|
||||
if (crossNorma < 0) {
|
||||
var _ = c;
|
||||
c = t;
|
||||
t = _;
|
||||
}
|
||||
|
||||
this.add(new TCAD.TWO.Constraints.LockConvex(c, a, t));
|
||||
};
|
||||
|
||||
TCAD.TWO.ParametricManager.prototype.tangent = function(objs) {
|
||||
var al = this._fetchArcCircAndLine(objs);
|
||||
var arc = al[0];
|
||||
|
|
@ -721,6 +771,25 @@ TCAD.TWO.ParametricManager.prototype.prepareForSubSystem = function(locked, subS
|
|||
return solver;
|
||||
};
|
||||
|
||||
TCAD.TWO.Constraints.ParentsCollector = function() {
|
||||
this.parents = [];
|
||||
var parents = this.parents;
|
||||
var index = {};
|
||||
function add(obj) {
|
||||
if (index[obj.id] === undefined) {
|
||||
index[obj.id] = obj;
|
||||
parents.push(obj);
|
||||
}
|
||||
}
|
||||
this.check = function(obj) {
|
||||
if (obj.parent !== null) {
|
||||
add(obj.parent);
|
||||
} else {
|
||||
add(obj);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
TCAD.TWO.Constraints.Factory = {};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------------------ //
|
||||
|
|
@ -1348,28 +1417,50 @@ TCAD.TWO.Constraints.Factory[TCAD.TWO.Constraints.Angle.prototype.NAME] = functi
|
|||
};
|
||||
|
||||
TCAD.TWO.Constraints.Angle.prototype.getObjects = function() {
|
||||
var out = [];
|
||||
var index = {};
|
||||
function add(obj) {
|
||||
if (index[obj.id] === undefined) {
|
||||
index[obj.id] = obj;
|
||||
out.push(obj);
|
||||
}
|
||||
}
|
||||
function check(obj) {
|
||||
if (obj.parent !== null) {
|
||||
add(obj.parent);
|
||||
} else {
|
||||
add(obj);
|
||||
}
|
||||
}
|
||||
check(this.p1);
|
||||
check(this.p2);
|
||||
check(this.p3);
|
||||
check(this.p4);
|
||||
return out;
|
||||
var collector = new TCAD.TWO.Constraints.ParentsCollector();
|
||||
collector.check(this.p1);
|
||||
collector.check(this.p2);
|
||||
collector.check(this.p3);
|
||||
collector.check(this.p4);
|
||||
return collector.parents;
|
||||
};
|
||||
|
||||
TCAD.TWO.Constraints.Angle.prototype.SettableFields = {'angle' : "Enter the angle value"};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------------------ //
|
||||
|
||||
/** @constructor */
|
||||
TCAD.TWO.Constraints.LockConvex = function(c, a, t) {
|
||||
this.c = c;
|
||||
this.a = a;
|
||||
this.t = t;
|
||||
};
|
||||
|
||||
TCAD.TWO.Constraints.LockConvex.prototype.NAME = 'LockConvex';
|
||||
TCAD.TWO.Constraints.LockConvex.prototype.UI_NAME = 'Lock Convexity';
|
||||
|
||||
TCAD.TWO.Constraints.LockConvex.prototype.getSolveData = function() {
|
||||
var params = [];
|
||||
this.c.collectParams(params);
|
||||
this.a.collectParams(params);
|
||||
this.t.collectParams(params);
|
||||
return [['LockConvex', params, []]];
|
||||
};
|
||||
|
||||
TCAD.TWO.Constraints.LockConvex.prototype.serialize = function() {
|
||||
return [this.NAME, [this.c.id, this.a.id, this.t.id]];
|
||||
};
|
||||
|
||||
TCAD.TWO.Constraints.Factory[TCAD.TWO.Constraints.LockConvex.prototype.NAME] = function(refs, data) {
|
||||
return new TCAD.TWO.Constraints.LockConvex(refs(data[0]), refs(data[1]), refs(data[2]));
|
||||
};
|
||||
|
||||
TCAD.TWO.Constraints.LockConvex.prototype.getObjects = function() {
|
||||
var collector = new TCAD.TWO.Constraints.ParentsCollector();
|
||||
collector.check(this.c);
|
||||
collector.check(this.a);
|
||||
collector.check(this.t);
|
||||
return collector.parents;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------------------ //
|
||||
99
web/img/vec/convex.svg
Normal file
99
web/img/vec/convex.svg
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="35"
|
||||
height="35"
|
||||
viewBox="0 0 34.999999 34.999996"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="convex.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="159.63273 : 549.86846 : 1"
|
||||
inkscape:vp_y="0 : 999.99987 : 0"
|
||||
inkscape:vp_z="744.09445 : 526.18102 : 1"
|
||||
inkscape:persp3d-origin="372.04723 : 350.78736 : 1"
|
||||
id="perspective4168" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#545454"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="15.535661"
|
||||
inkscape:cx="12.681338"
|
||||
inkscape:cy="24.986016"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:snap-bbox="false"
|
||||
inkscape:snap-global="true"
|
||||
inkscape:window-width="1858"
|
||||
inkscape:window-height="1178"
|
||||
inkscape:window-x="54"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
units="px"
|
||||
width="100mm" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1017.3622)">
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.76900005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 4.1992958,1022.4097 13.3656642,25.6954 13.297765,-25.9348"
|
||||
id="path4184"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.35827634px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="path3336-3"
|
||||
cx="30.077709"
|
||||
cy="1023.4678"
|
||||
r="3.3208618" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.35827634px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="path3336-3-0"
|
||||
cx="4.3586669"
|
||||
cy="1022.4956"
|
||||
r="3.3208618" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.35827634px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="path3336-3-7"
|
||||
cx="17.443739"
|
||||
cy="1047.6632"
|
||||
r="3.3208618" />
|
||||
<path
|
||||
style="fill:#00ff00;fill-opacity:0.18934911;stroke:none;stroke-width:0.12873608;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 15.97966,24.63144 C 15.35824,23.435127 13.259765,19.400453 11.316384,15.665498 L 7.7829621,8.8746696 12.633078,8.858173 c 2.667563,-0.00907 7.034303,-0.00907 9.703865,0 l 4.853749,0.016497 -4.589179,8.947157 -4.589177,8.947157 -0.45141,0.01879 -0.451411,0.01879 -1.129855,-2.175115 z"
|
||||
id="path4185"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(0,1017.3622)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
|
|
@ -88,6 +88,7 @@
|
|||
<button class="btn rbtn act-pointInMiddle" style="background-image: url(img/vec/pointInMiddle.svg);"></button>
|
||||
<button class="btn rbtn act-llAngle" style="background-image: url(img/vec/angle.svg);"></button>
|
||||
<button class="btn rbtn act-symmetry" style="background-image: url(img/vec/symmetry.svg);"></button>
|
||||
<button class="btn rbtn act-lockConvex" style="background-image: url(img/vec/convex.svg);"></button>
|
||||
<button class="btn rbtn act-lockConstraint" ><i class="fa fa-lock"></i></button>
|
||||
</div>
|
||||
<div style="background: black; overflow: hidden; height: 100%;">
|
||||
|
|
|
|||
Loading…
Reference in a new issue