Skip to content

Commit f8acd49

Browse files
committed
Reimplement profile view
1 parent 92e1eb7 commit f8acd49

12 files changed

Lines changed: 117 additions & 66 deletions

File tree

gui/CMakeLists.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,6 @@ add_executable(
136136
source/pre/views/docks/EditDock.hpp
137137
source/pre/views/docks/PlotDock.cpp
138138
source/pre/views/docks/PlotDock.hpp
139-
source/pre/views/limb2d/ProfileView.cpp
140-
source/pre/views/limb2d/ProfileView.hpp
141-
source/pre/views/limb2d/WidthPlotView.cpp
142-
source/pre/views/limb2d/WidthPlotView.hpp
143-
source/pre/views/limb2d/HeightPlotView.cpp
144-
source/pre/views/limb2d/HeightPlotView.hpp
145139
source/pre/views/primitive/DoubleView.hpp
146140
source/pre/views/primitive/DoubleView.cpp
147141
source/pre/views/primitive/ColorView.hpp
@@ -182,6 +176,12 @@ add_executable(
182176
source/pre/views/MassesView.cpp
183177
source/pre/views/DampingView.hpp
184178
source/pre/views/DampingView.cpp
179+
source/pre/views/limb2d/ProfilePlotView.cpp
180+
source/pre/views/limb2d/ProfilePlotView.hpp
181+
source/pre/views/limb2d/WidthPlotView.cpp
182+
source/pre/views/limb2d/WidthPlotView.hpp
183+
source/pre/views/limb2d/HeightPlotView.cpp
184+
source/pre/views/limb2d/HeightPlotView.hpp
185185
source/pre/views/limb3d/ErrorLabel.cpp
186186
source/pre/views/limb3d/ErrorLabel.hpp
187187
source/pre/views/limb3d/LayerColors.cpp

gui/source/post/ShapePlot.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ void ShapePlot::updateBackgroundStates() {
8787

8888
if(intermediate_states >= 0) {
8989
// Unbraced state
90-
plotLimbOutline(limb_left[intermediate_states], limb_right[intermediate_states], common.limb.position);
90+
plotLimbOutline(limb_left[intermediate_states], limb_right[intermediate_states], common.limb.position_eval);
9191
}
9292
}
9393

@@ -120,7 +120,7 @@ void ShapePlot::updateAxes() {
120120
}
121121
};
122122

123-
expand3(common.limb.position);
123+
expand3(common.limb.position_eval);
124124
for(size_t i = 0; i < states.time.size(); ++i) {
125125
// Add 0.5*height as an estimated upper bound
126126
//expand(states.x_pos_limb[i] + 0.5*limb.height, states.y_pos_limb[i] + 0.5*limb.height);

gui/source/pre/views/SpiralView.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ SpiralView::SpiralView(SpiralModel* model) {
1212

1313
addProperty(
1414
"Radius (start)",
15-
new DoubleView(model, model->RADIUS_START, Quantities::length, DoubleRange::unrestricted(1e-3), "Start radius of the spiral segment")
15+
new DoubleView(model, model->RADIUS_START, Quantities::length, DoubleRange::unrestricted(1e-3), "Start radius of the spiral segment (or zero for no radius)")
1616
);
1717

1818
addProperty(
1919
"Radius (end)",
20-
new DoubleView(model, model->RADIUS_END, Quantities::length, DoubleRange::unrestricted(1e-3), "End radius of the spiral segment")
20+
new DoubleView(model, model->RADIUS_END, Quantities::length, DoubleRange::unrestricted(1e-3), "End radius of the spiral segment (or zero for no radius)")
2121
);
2222

2323
addStretch();

gui/source/pre/views/docks/PlotDock.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "pre/models/MainTreeModel.hpp"
44
#include "pre/views/limb2d/WidthPlotView.hpp"
55
#include "pre/views/limb2d/HeightPlotView.hpp"
6+
#include "pre/views/limb2d/ProfilePlotView.hpp"
67
#include <QItemSelectionModel>
78
#include <QLabel>
89

@@ -18,32 +19,32 @@ class PlaceholderLabel: public QLabel {
1819
}
1920
};
2021

21-
PlotDock::PlotDock(MainModel* viewModel) {
22+
PlotDock::PlotDock(MainModel* model) {
2223
placeholder = new PlaceholderLabel();
2324

2425
this->setWindowTitle("Graph");
2526
this->setObjectName("PlotView"); // Required to save state of main window
2627
this->setFeatures(QDockWidget::NoDockWidgetFeatures);
2728
this->setWidget(placeholder);
2829

29-
auto selectionModel = viewModel->getModelTreeSelectionModel();
30+
auto selectionModel = model->getModelTreeSelectionModel();
3031
QObject::connect(selectionModel, &QItemSelectionModel::selectionChanged, this, [=] {
3132
QModelIndexList selection = selectionModel->selectedIndexes();
3233
if(selection.size() == 1) {
3334
QPersistentModelIndex index(selection.first());
3435

3536
if(index.internalId() == ItemType::LAYER) {
36-
showPlot(index, [=]{ return new HeightPlotView(viewModel, index); });
37+
showPlot(index, [=]{ return new HeightPlotView(model, index); });
3738
return;
3839
}
3940

40-
if(index.internalId() == ItemType::SEGMENT) {
41-
showPlot(index, [=]{ return new QLabel("Profile"); });
41+
if(index.internalId() == ItemType::TOPLEVEL && index.row() == TopLevelItem::WIDTH) {
42+
showPlot(index, [=]{ return new WidthPlotView(model); });
4243
return;
4344
}
4445

45-
if(index.internalId() == ItemType::TOPLEVEL && index.row() == TopLevelItem::WIDTH) {
46-
showPlot(index, [=]{ return new WidthPlotView(viewModel); });
46+
if((index.internalId() == ItemType::TOPLEVEL && index.row() == TopLevelItem::PROFILE) || index.internalId() == ItemType::SEGMENT) {
47+
showPlot(index, [=]{ return new ProfilePlotView(model); });
4748
return;
4849
}
4950
}

gui/source/pre/views/docks/PlotDock.hpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,11 @@ class MainModel;
99

1010
class PlotDock: public QDockWidget {
1111
public:
12-
PlotDock(MainModel* viewModel);
12+
PlotDock(MainModel* model);
1313

1414
void showPlaceholder();
1515
void showPlot(QPersistentModelIndex index, const std::function<QWidget*()>& create);
1616

17-
/*
18-
template<typename F>
19-
void showPlot(QPersistentModelIndex index, const F& f) {
20-
if(!plots.contains(index)) {
21-
qInfo() << "Construct " << index;
22-
plots.insert(index, f());
23-
}
24-
25-
setWidget(plots[index]);
26-
}
27-
*/
28-
2917
private:
3018
QLabel* placeholder;
3119
QMap<QPersistentModelIndex, QWidget*> plots;

gui/source/pre/views/limb2d/ProfileView.cpp renamed to gui/source/pre/views/limb2d/ProfilePlotView.cpp

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,34 @@
1-
#include "ProfileView.hpp"
2-
#include "solver/BowModel.hpp"
1+
#include "ProfilePlotView.hpp"
2+
#include "pre/models/MainModel.hpp"
3+
#include "pre/models/units/UnitSystem.hpp"
34

45
// Magic numbers
56
const size_t N_SEGMENT_POINTS = 100;
67
const size_t N_CURVATURE_POINTS = 200;
78
const double CURVATURE_SCALING = 0.05;
89

9-
ProfileView::ProfileView(const Quantity& quantity)
10-
: quantity(quantity)
10+
ProfilePlotView::ProfilePlotView(MainModel* model):
11+
model(model)
1112
{
1213
this->setAspectPolicy(PlotWidget::SCALE_Y);
1314

15+
// Line
16+
curveLine = new QCPCurve(this->xAxis, this->yAxis);
17+
curveLine->setName("Line");
18+
curveLine->setPen({Qt::blue, 2});
19+
20+
// Control points
21+
curvePoints = new QCPCurve(this->xAxis, this->yAxis);
22+
curvePoints->setName("Points");
23+
curvePoints->setScatterStyle({QCPScatterStyle::ssSquare, Qt::blue, 8});
24+
curvePoints->setLineStyle(QCPCurve::lsNone);
25+
26+
// Selected points
27+
curveSelected = new QCPCurve(this->xAxis, this->yAxis);
28+
curveSelected->setName("Selected");
29+
curveSelected->setScatterStyle({QCPScatterStyle::ssSquare, Qt::red, Qt::red, 8});
30+
curveSelected->setLineStyle(QCPCurve::lsNone);
31+
1432
// Menu actions
1533

1634
action_show_curvature = new QAction("Show curvature", this);
@@ -35,28 +53,57 @@ ProfileView::ProfileView(const Quantity& quantity)
3553
this->contextMenu()->insertSeparator(before);
3654

3755
// Update on unit changes
38-
QObject::connect(&quantity, &Quantity::unitChanged, this, &ProfileView::updatePlot);
56+
//QObject::connect(&quantity, &Quantity::unitChanged, this, &ProfilePlotView::updatePlot);
57+
58+
// Update on unit and geometry changes
59+
QObject::connect(&Quantities::length, &Quantity::unitChanged, this, &ProfilePlotView::updatePlot);
60+
QObject::connect(model, &MainModel::geometryChanged, this, &ProfilePlotView::updatePlot);
61+
62+
// Initial update
63+
updatePlot();
3964
}
4065

41-
void ProfileView::setData(const Profile& data) {
66+
/*
67+
void ProfilePlotView::setData(const Profile& data) {
4268
input = data;
4369
updatePlot();
4470
}
4571
46-
void ProfileView::setSelection(const QList<int>& indices) {
72+
void ProfilePlotView::setSelection(const QList<int>& indices) {
4773
selection = indices;
4874
updateSelection();
4975
this->replot();
5076
}
77+
*/
5178

52-
void ProfileView::updatePlot() {
53-
//throw std::invalid_argument("Removed code");
54-
/*
55-
this->xAxis->setLabel("X " + quantity.getUnit().getLabel());
56-
this->yAxis->setLabel("Y " + quantity.getUnit().getLabel());
79+
void ProfilePlotView::updatePlot() {
80+
this->xAxis->setLabel("X " + Quantities::length.getUnit().getSuffix());
81+
this->yAxis->setLabel("Y " + Quantities::length.getUnit().getSuffix());
5782

58-
this->clearPlottables();
83+
curveLine->data()->clear();
84+
curvePoints->data()->clear();
85+
curveSelected->data()->clear();
5986

87+
if(model->hasGeometry()) {
88+
for(auto& point: model->getGeometry().position_eval) {
89+
curveLine->addData(
90+
Quantities::length.getUnit().fromBase(point[0]),
91+
Quantities::length.getUnit().fromBase(point[1])
92+
);
93+
}
94+
95+
for(auto& point: model->getGeometry().position_control) {
96+
curvePoints->addData(
97+
Quantities::length.getUnit().fromBase(point[0]),
98+
Quantities::length.getUnit().fromBase(point[1])
99+
);
100+
}
101+
}
102+
103+
this->rescaleAxes();
104+
this->replot();
105+
106+
/*
60107
// Construct profile curve segment by segment, stop on first error
61108
ProfileCurve profile;
62109
try {
@@ -147,13 +194,11 @@ void ProfileView::updatePlot() {
147194
148195
updateSelection();
149196
updateVisibility();
150-
151-
this->rescaleAxes();
152-
this->replot();
153197
*/
154198
}
155199

156-
void ProfileView::updateSelection() {
200+
void ProfilePlotView::updateSelection() {
201+
/*
157202
for(int i = 0; i < segment_curves.size(); ++i) {
158203
if(selection.contains(i)) {
159204
segment_curves[i]->setPen({Qt::red, 2});
@@ -177,14 +222,17 @@ void ProfileView::updateSelection() {
177222
segment_nodes[i]->setScatterSkip(0);
178223
}
179224
}
225+
*/
180226
}
181227

182-
void ProfileView::updateVisibility() {
228+
void ProfilePlotView::updateVisibility() {
229+
/*
183230
for(auto line: curvature_lines) {
184231
line->setVisible(action_show_curvature->isChecked());
185232
}
186233
187234
for(auto segment_node: segment_nodes) {
188235
segment_node->setVisible(action_show_nodes->isChecked());
189236
}
237+
*/
190238
}

gui/source/pre/views/limb2d/ProfileView.hpp renamed to gui/source/pre/views/limb2d/ProfilePlotView.hpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
11
#pragma once
22
#include "pre/widgets/PlotWidget.hpp"
3-
#include "pre/models/units/Quantity.hpp"
4-
#include "solver/BowModel.hpp"
53

6-
class ProfileView: public PlotWidget
4+
class MainModel;
5+
6+
class ProfilePlotView: public PlotWidget
77
{
88
public:
9-
ProfileView(const Quantity& xy_quantity);
9+
ProfilePlotView(MainModel* model);
10+
/*
1011
void setData(const Profile& data);
1112
void setSelection(const QList<int>& indices);
13+
*/
1214

1315
private:
14-
const Quantity& quantity;
16+
MainModel* model;
1517

1618
QAction* action_show_curvature;
1719
QAction* action_show_nodes;
1820

19-
Profile input;
20-
QList<int> selection;
21-
22-
QList<QCPCurve*> segment_curves;
23-
QList<QCPCurve*> segment_nodes; // TODO: Use some item type for this?
24-
QList<QCPCurve*> curvature_lines;
21+
QCPCurve* curveLine;
22+
QCPCurve* curvePoints;
23+
QCPCurve* curveSelected;
2524

2625
void updatePlot();
2726
void updateSelection();

gui/source/pre/views/limb3d/LimbMesh.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ LimbMesh::LimbMesh(const BowModel& bow, const LimbInfo& geometry)
2626

2727
// Iterate over segments, i.e. pairs of a previous and a next cross section
2828
for(size_t iSegment = 0; iSegment < nSegments; ++iSegment) {
29-
std::array<double, 3> profile_prev = geometry.position[iSegment];
30-
std::array<double, 3> profile_next = geometry.position[iSegment + 1];
29+
std::array<double, 3> profile_prev = geometry.position_eval[iSegment];
30+
std::array<double, 3> profile_next = geometry.position_eval[iSegment + 1];
3131

3232
QVector3D center_prev ( profile_prev[0], profile_prev[1], 0.0 );
3333
QVector3D normal_w_prev( 0.0, 0.0, 1.0 );

gui/source/solver/BowResult.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(
3535

3636
struct LimbInfo {
3737
std::vector<double> length;
38-
std::vector<std::array<double, 3>> position;
38+
std::vector<std::array<double, 3>> position_eval;
39+
std::vector<std::array<double, 3>> position_control;
3940
std::vector<double> width;
4041
std::vector<double> height;
4142
std::vector<std::vector<double>> bounds;
@@ -47,7 +48,8 @@ struct LimbInfo {
4748
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(
4849
LimbInfo,
4950
length,
50-
position,
51+
position_eval,
52+
position_control,
5153
width,
5254
height,
5355
bounds,

rust/virtualbow/src/geometry.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ pub struct DiscreteLimbGeometry {
2525
pub y_nodes: Vec<DVector<f64>>, // Layer bounds at nodes (y in cross section coordinates)
2626
pub h_nodes: Vec<DVector<f64>>, // Layer heights at nodes
2727

28+
pub p_control: Vec<SVector<f64, 3>>, // Positions (x, y, φ) of the control points
29+
2830
pub n_eval: Vec<f64>, // Relative lengths at which the limb quantities are evaluated
2931
pub s_eval: Vec<f64>, // Arc lengths at which the limb quantities are evaluated
3032
pub p_eval: Vec<SVector<f64, 3>>, // Positions (x, y, φ) of the evaluation points
@@ -87,6 +89,9 @@ impl LimbGeometry {
8789
let y_nodes = n_nodes.iter().map(|&n| self.section.layer_bounds(n).0).collect_vec();
8890
let h_nodes = n_nodes.iter().map(|&n| self.section.layer_bounds(n).1).collect_vec(); // TODO: Collect in one step
8991

92+
// Control points of the profile curve
93+
let p_control = self.profile.get_nodes().iter().map(|node| vector![node.r[0], node.r[1], node.φ]).collect(); // TODO: Make those conversions unnecessary by using a single format for curve points
94+
9095
// Equidistant evaluation points along the length of the limb
9196
let s_eval = lin_space(self.profile.s_start()..=self.profile.s_end(), n_eval_points).collect_vec();
9297
let n_eval = s_eval.iter().map(|&s| self.profile.normalize(s)).collect_vec();
@@ -124,6 +129,7 @@ impl LimbGeometry {
124129
p_nodes,
125130
y_nodes,
126131
h_nodes,
132+
p_control,
127133
n_eval,
128134
s_eval,
129135
y_eval,
@@ -140,7 +146,8 @@ impl DiscreteLimbGeometry {
140146
pub fn to_limb_info(&self) -> LimbInfo {
141147
LimbInfo {
142148
length: self.s_eval.clone(),
143-
position: self.p_eval.clone(),
149+
position_eval: self.p_eval.clone(),
150+
position_control: self.p_control.clone(),
144151
width: self.w_eval.clone(),
145152
height: self.h_eval.iter().map(|h| h.sum()).collect(),
146153
bounds: self.y_eval.iter().map(|y| y.data.clone().into()).collect(),

0 commit comments

Comments
 (0)