Skip to content

Commit

Permalink
Add ability to constrain cardinality for LineLength constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
Tom committed Nov 25, 2023
1 parent 3bf3745 commit 18f59ca
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 37 deletions.
54 changes: 48 additions & 6 deletions detailer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use drawing::Handler;
use drawing::{handler::ToolResponse, tools, Data, Feature, FeatureKey, FeatureMeta};
use drawing::{Constraint, ConstraintKey, ConstraintMeta, DimensionDisplay};
use drawing::{Axis, Constraint, ConstraintKey, ConstraintMeta, DimensionDisplay};

#[derive(Debug, Default, Clone, PartialEq)]
pub enum Tab {
Expand Down Expand Up @@ -131,13 +131,14 @@ impl<'a> Widget<'a> {
y,
)
}
Some(Constraint::LineLength(meta, _, d, dd)) => {
Some(Constraint::LineLength(meta, _, d, axis, dd)) => {
Widget::show_constraint_line_length(
ui,
&mut commands,
&mut changed,
&ck,
d,
axis,
dd,
meta,
)
Expand Down Expand Up @@ -205,12 +206,13 @@ impl<'a> Widget<'a> {
changed: &mut bool,
k: &ConstraintKey,
d: &mut f32,
axis: &mut Option<Axis>,
_ref_pt: &mut DimensionDisplay,
meta: &mut ConstraintMeta,
) {
let text_height = egui::TextStyle::Body.resolve(ui.style()).size;
ui.horizontal(|ui| {
let r = ui.available_size();
let text_height = egui::TextStyle::Body.resolve(ui.style()).size;

let text_rect = ui.add(egui::Label::new("Length").wrap(false)).rect;
ui.add_space(r.x / 2. - text_rect.width() - ui.spacing().item_spacing.x);
Expand All @@ -234,22 +236,62 @@ impl<'a> Widget<'a> {
}
});
});

ui.horizontal(|ui| {
let r = ui.available_size();

match axis {
Some(a) => {
let text_rect = ui.add(egui::Label::new("⏵ Cardinality").wrap(false)).rect;
ui.add_space(r.x / 2. - text_rect.width() - ui.spacing().item_spacing.x);

match a {
Axis::TopBottom => ui.label("+V"),
Axis::LeftRight => ui.label("+H"),
};

ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| {
if ui.button("⊗").clicked() {
*axis = None;
*changed = true;
}
});
}
None => {
let r = ui.available_size();

let text_rect = ui
.add(egui::Label::new("⏵ Constrain cardinality").wrap(false))
.rect;
ui.add_space(r.x / 2. - text_rect.width() - ui.spacing().item_spacing.x);

if ui.button("+V").clicked() {
*axis = Some(Axis::TopBottom);
*changed = true;
}
if ui.button("+H").clicked() {
*axis = Some(Axis::LeftRight);
*changed = true;
}
}
};
});
}

fn show_constraint_line_cardinal_align(
ui: &mut egui::Ui,
commands: &mut Vec<ToolResponse>,
changed: &mut bool,
k: &ConstraintKey,
is_horizontal: &mut bool,
axis: &mut Axis,
) {
ui.horizontal(|ui| {
let r = ui.available_size();
let text_height = egui::TextStyle::Body.resolve(ui.style()).size;

let text_rect = ui
.add(
egui::Label::new(if *is_horizontal {
egui::Label::new(if *axis == Axis::LeftRight {
"Horizontal"
} else {
"Vertical"
Expand All @@ -266,7 +308,7 @@ impl<'a> Widget<'a> {

if resp.clicked() {
*changed |= true;
*is_horizontal = !*is_horizontal;
axis.swap();
}

ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| {
Expand Down
116 changes: 92 additions & 24 deletions drawing/src/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,33 @@ pub struct DimensionDisplay {
pub(crate) y: f32,
}

#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize, PartialEq)]
pub enum Axis {
#[default]
LeftRight,
TopBottom,
}

impl Axis {
pub fn swap(&mut self) {
*self = match self {
Axis::TopBottom => Axis::LeftRight,
Axis::LeftRight => Axis::TopBottom,
}
}
}

#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub enum Constraint {
Fixed(ConstraintMeta, FeatureKey, f32, f32),
LineLength(ConstraintMeta, FeatureKey, f32, DimensionDisplay),
LineAlongCardinal(ConstraintMeta, FeatureKey, bool), // true = horizontal
LineLength(
ConstraintMeta,
FeatureKey,
f32,
Option<Axis>,
DimensionDisplay,
),
LineAlongCardinal(ConstraintMeta, FeatureKey, Axis),
}

impl Constraint {
Expand Down Expand Up @@ -64,7 +86,7 @@ impl Constraint {
use Constraint::{Fixed, LineAlongCardinal, LineLength};
match self {
Fixed(..) => None,
LineLength(_, fk, _, dd) => {
LineLength(_, fk, _, _, dd) => {
if let Some(Feature::LineSegment(_, f1, f2)) = drawing.features.get(*fk) {
let (a, b) = match (
drawing.features.get(*f1).unwrap(),
Expand Down Expand Up @@ -132,7 +154,7 @@ impl Constraint {
};
}

LineLength(_, k, d, dd) => {
LineLength(_, k, d, axis, dd) => {
if let Some(Feature::LineSegment(_, f1, f2)) = drawing.features.get(*k) {
let (a, b) = match (
drawing.features.get(*f1).unwrap(),
Expand All @@ -147,7 +169,11 @@ impl Constraint {
crate::l::draw::DimensionLengthOverlay {
a,
b,
val: &format!("{:.3}", d),
val: &match axis {
None => format!("{:.3}", d),
Some(Axis::LeftRight) => format!("H+{:.3}", d),
Some(Axis::TopBottom) => format!("V+{:.3}", d),
},
reference: egui::Vec2::new(dd.x, dd.y),
hovered: params.hovered,
selected: params.selected,
Expand All @@ -156,7 +182,7 @@ impl Constraint {
}
}

LineAlongCardinal(_, k, is_horizontal) => {
LineAlongCardinal(_, k, axis) => {
if let Some(Feature::LineSegment(_, f1, f2)) = drawing.features.get(*k) {
let (a, b) = match (
drawing.features.get(*f1).unwrap(),
Expand All @@ -172,7 +198,7 @@ impl Constraint {
painter.text(
mid,
egui::Align2::CENTER_CENTER,
if *is_horizontal { "H" } else { "V" },
if *axis == Axis::LeftRight { "H" } else { "V" },
params.font_id.clone(),
egui::Color32::WHITE,
);
Expand Down Expand Up @@ -206,7 +232,7 @@ impl Constraint {
),
]
}
LineLength(_, k, d, _) => {
LineLength(_, k, d, axis, _) => {
if let Some(Feature::LineSegment(_, f1, f2)) = drawing.features.get(*k) {
let td = &drawing.terms.get_feature_term(*k, TermType::ScalarDistance);
let (x1, y1, x2, y2) = (
Expand All @@ -216,25 +242,67 @@ impl Constraint {
&drawing.terms.get_feature_term(*f2, TermType::PositionY),
);

vec![
Expression::Equal(
Box::new(Expression::Variable(td.into())),
Box::new(Expression::Rational(
Rational::from_float(*d).unwrap(),
true,
)),
),
Expression::Equal(
Box::new(Expression::Variable(td.into())),
Box::new(distance_eq(td, x1, y1, x2, y2)),
),
]
match axis {
Some(Axis::LeftRight) => vec![
Expression::Equal(
Box::new(Expression::Variable(td.into())),
Box::new(Expression::Rational(
Rational::from_float(*d).unwrap(),
true,
)),
),
Expression::Equal(
Box::new(Expression::Variable(td.into())),
Box::new(Expression::Difference(
Box::new(Expression::Variable(x2.into())),
Box::new(Expression::Variable(x1.into())),
)),
),
Expression::Equal(
Box::new(Expression::Variable(y2.into())),
Box::new(Expression::Variable(y1.into())),
),
],
Some(Axis::TopBottom) => vec![
Expression::Equal(
Box::new(Expression::Variable(td.into())),
Box::new(Expression::Rational(
Rational::from_float(*d).unwrap(),
true,
)),
),
Expression::Equal(
Box::new(Expression::Variable(td.into())),
Box::new(Expression::Difference(
Box::new(Expression::Variable(y1.into())),
Box::new(Expression::Variable(y2.into())),
)),
),
Expression::Equal(
Box::new(Expression::Variable(x2.into())),
Box::new(Expression::Variable(x1.into())),
),
],
None => vec![
Expression::Equal(
Box::new(Expression::Variable(td.into())),
Box::new(Expression::Rational(
Rational::from_float(*d).unwrap(),
true,
)),
),
Expression::Equal(
Box::new(Expression::Variable(td.into())),
Box::new(distance_eq(td, x1, y1, x2, y2)),
),
],
}
} else {
unreachable!();
}
}

LineAlongCardinal(_, k, is_horizontal) => {
LineAlongCardinal(_, k, axis) => {
if let Some(Feature::LineSegment(_, f1, f2)) = drawing.features.get(*k) {
let (x1, y1, x2, y2) = (
&drawing.terms.get_feature_term(*f1, TermType::PositionX),
Expand All @@ -243,7 +311,7 @@ impl Constraint {
&drawing.terms.get_feature_term(*f2, TermType::PositionY),
);

if *is_horizontal {
if *axis == Axis::LeftRight {
vec![Expression::Equal(
Box::new(Expression::Variable(y1.into())),
Box::new(Expression::Variable(y2.into())),
Expand Down Expand Up @@ -299,7 +367,7 @@ impl system::ConstraintProvider<ConstraintResidualIter> for Constraint {
x_ref: allocator.get_feature_term(*k, TermType::PositionX),
y_ref: allocator.get_feature_term(*k, TermType::PositionY),
},
LineLength(_, k, d, _) => {
LineLength(_, k, d, ..) => {
if let Some(Feature::LineSegment(_, f1, f2)) = features.get(*k) {
ConstraintResidualIter::PointDistance {
count: 0,
Expand Down
4 changes: 2 additions & 2 deletions drawing/src/data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ impl Data {

/// NOTE: Only supports LineLength constraints atm, and consumes a SCREEN coordinate.
pub fn move_constraint(&mut self, k: ConstraintKey, pos: egui::Pos2) {
if let Some(Constraint::LineLength(_, fk, _, _)) = self.constraints.get(k) {
if let Some(Constraint::LineLength(_, fk, ..)) = self.constraints.get(k) {
let (a, b) = match self.features.get(*fk) {
Some(Feature::LineSegment(_, f1, f2)) => {
let (a, b) = match (
Expand All @@ -296,7 +296,7 @@ impl Data {
}
};

if let Some(Constraint::LineLength(_, fk, _, dd)) = self.constraint_mut(k) {
if let Some(Constraint::LineLength(_, fk, _, _, dd)) = self.constraint_mut(k) {

Check warning on line 299 in drawing/src/data/mod.rs

View workflow job for this annotation

GitHub Actions / Check

unused variable: `fk`

Check warning on line 299 in drawing/src/data/mod.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused variable: `fk`
let c = a.lerp(b, 0.5);
let v = c.to_vec2() - pos.to_vec2();
let reference = egui::Vec2::angled((a - b).angle() - v.angle()) * v.length();
Expand Down
9 changes: 7 additions & 2 deletions drawing/src/handler.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::{Data, Feature, FeatureKey, FeatureMeta};
use crate::tools::Toolbar;
use crate::{Constraint, ConstraintKey, ConstraintMeta, DimensionDisplay};
use crate::{Axis, Constraint, ConstraintKey, ConstraintMeta, DimensionDisplay};

#[derive(Debug)]
pub enum ToolResponse {
Expand Down Expand Up @@ -92,6 +92,7 @@ impl Handler {
ConstraintMeta::default(),
k,
d,
None,
DimensionDisplay { x: 0., y: 35.0 },
));

Expand All @@ -118,7 +119,11 @@ impl Handler {
drawing.add_constraint(Constraint::LineAlongCardinal(
ConstraintMeta::default(),
k,
is_horizontal,
if is_horizontal {
Axis::LeftRight
} else {
Axis::TopBottom
},
));

tools.clear();
Expand Down
6 changes: 3 additions & 3 deletions drawing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub use data::{Data, Hover, Viewport};
mod feature;
pub use feature::{Feature, FeatureKey, FeatureMeta};
mod constraints;
pub use constraints::{Constraint, ConstraintKey, ConstraintMeta, DimensionDisplay};
pub use constraints::{Axis, Constraint, ConstraintKey, ConstraintMeta, DimensionDisplay};
pub mod handler;
mod system;
pub use handler::Handler;
Expand Down Expand Up @@ -153,7 +153,7 @@ impl<'a> Widget<'a> {
(
Hover::Constraint {
k,
constraint: Constraint::LineLength(_, _, _, dd),
constraint: Constraint::LineLength(_, _, _, _, dd),
},
true,
false,
Expand All @@ -167,7 +167,7 @@ impl<'a> Widget<'a> {
(
Hover::Constraint {
k,
constraint: Constraint::LineLength(_, _, _, dd),
constraint: Constraint::LineLength(_, _, _, _, dd),
},
false,
true,
Expand Down

0 comments on commit 18f59ca

Please sign in to comment.