Skip to content

Commit 14dd53d

Browse files
committed
New constraint, DistanceVar
Just like the existing euclidean distance constraint, except the distance is a variable not a constant. Math notebook: KittyCAD/ezpz-sympy#3
1 parent 4110e12 commit 14dd53d

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

kcl-ezpz/src/constraints.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ pub enum Constraint {
3737
CircleTangentToCircle(DatumCircle, DatumCircle),
3838
/// These two points should be a given distance apart.
3939
Distance(DatumPoint, DatumPoint, f64),
40+
/// These two points should have distance equal to the given variable.
41+
DistanceVar(DatumPoint, DatumPoint, DatumDistance),
4042
/// These two points should be a given vertical distance apart.
4143
VerticalDistance(DatumPoint, DatumPoint, f64),
4244
/// These two points should be a given horizontal distance apart.
@@ -114,6 +116,11 @@ impl Constraint {
114116
row0.extend(p0.all_variables());
115117
row0.extend(p1.all_variables());
116118
}
119+
Constraint::DistanceVar(p0, p1, d) => {
120+
row0.extend(p0.all_variables());
121+
row0.extend(p1.all_variables());
122+
row0.extend(d.all_variables());
123+
}
117124
Constraint::VerticalDistance(p0, p1, _dist) => {
118125
row0.extend([p0.id_y(), p1.id_y()]);
119126
}
@@ -300,6 +307,15 @@ impl Constraint {
300307
let actual_distance = p0.euclidean_distance(p1);
301308
*residual0 = actual_distance - expected_distance;
302309
}
310+
Constraint::DistanceVar(p, q, d) => {
311+
let px = current_assignments[layout.index_of(p.id_x())];
312+
let py = current_assignments[layout.index_of(p.id_y())];
313+
let qx = current_assignments[layout.index_of(q.id_x())];
314+
let qy = current_assignments[layout.index_of(q.id_y())];
315+
let d = current_assignments[layout.index_of(d.id)];
316+
let residual = -d + ((px - qx).powi(2) + (py - qy).powi(2)).sqrt();
317+
*residual0 = residual;
318+
}
303319
Constraint::VerticalDistance(p0, p1, expected_distance) => {
304320
let p0_y = current_assignments[layout.index_of(p0.id_y())];
305321
let p1_y = current_assignments[layout.index_of(p1.id_y())];
@@ -678,6 +694,7 @@ impl Constraint {
678694
Constraint::LineTangentToCircle(..) => 1,
679695
Constraint::CircleTangentToCircle(..) => 1,
680696
Constraint::Distance(..) => 1,
697+
Constraint::DistanceVar(..) => 1,
681698
Constraint::VerticalDistance(..) => 1,
682699
Constraint::HorizontalDistance(..) => 1,
683700
Constraint::Vertical(..) => 1,
@@ -923,6 +940,43 @@ impl Constraint {
923940
.as_slice(),
924941
);
925942
}
943+
Constraint::DistanceVar(p, q, d) => {
944+
let px = current_assignments[layout.index_of(p.id_x())];
945+
let py = current_assignments[layout.index_of(p.id_y())];
946+
let qx = current_assignments[layout.index_of(q.id_x())];
947+
let qy = current_assignments[layout.index_of(q.id_y())];
948+
// let d = current_assignments[layout.index_of(d.id)];
949+
let df_dpx = (px - qx) * ((px - qx).powi(2) + (py - qy).powi(2)).sqrt().recip();
950+
let df_dpy = (py - qy) * ((px - qx).powi(2) + (py - qy).powi(2)).sqrt().recip();
951+
let df_dqx = -(px - qx) * ((px - qx).powi(2) + (py - qy).powi(2)).sqrt().recip();
952+
let df_dqy = -(py - qy) * ((px - qx).powi(2) + (py - qy).powi(2)).sqrt().recip();
953+
let df_dd = -1.0;
954+
row0.extend(
955+
[
956+
JacobianVar {
957+
id: p.id_x(),
958+
partial_derivative: df_dpx,
959+
},
960+
JacobianVar {
961+
id: p.id_y(),
962+
partial_derivative: df_dpy,
963+
},
964+
JacobianVar {
965+
id: q.id_x(),
966+
partial_derivative: df_dqx,
967+
},
968+
JacobianVar {
969+
id: q.id_y(),
970+
partial_derivative: df_dqy,
971+
},
972+
JacobianVar {
973+
id: d.id,
974+
partial_derivative: df_dd,
975+
},
976+
]
977+
.as_slice(),
978+
);
979+
}
926980
Constraint::VerticalDistance(p0, p1, _expected_distance) => {
927981
// Residual: p0y - p1y - d = 0
928982
// ∂R/∂y0 = 1
@@ -1888,6 +1942,7 @@ impl Constraint {
18881942
Constraint::LineTangentToCircle(..) => "LineTangentToCircle",
18891943
Constraint::CircleTangentToCircle(..) => "CircleTangentToCircle",
18901944
Constraint::Distance(..) => "Distance",
1945+
Constraint::DistanceVar(..) => "DistanceVar",
18911946
Constraint::VerticalDistance(..) => "VerticalDistance",
18921947
Constraint::HorizontalDistance(..) => "HorizontalDistance",
18931948
Constraint::Vertical(..) => "Vertical",

0 commit comments

Comments
 (0)