Skip to content

Commit 8131303

Browse files
committed
Reenable curvature and node options on input geometry plots
1 parent fef55d0 commit 8131303

10 files changed

Lines changed: 90 additions & 155 deletions

File tree

gui/source/pre/views/limb2d/HeightPlotView.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ HeightPlotView::HeightPlotView(MainModel* model, QPersistentModelIndex index):
2727
action_show_nodes->setCheckable(true);
2828
action_show_nodes->setChecked(true);
2929
QObject::connect(action_show_nodes, &QAction::triggered, [&](bool checked) {
30-
//setNodesVisible(checked);
30+
setNodesVisible(checked);
3131
replot();
3232
});
3333

@@ -95,6 +95,11 @@ void HeightPlotView::updatePlot() {
9595
}
9696
}
9797

98-
this->rescaleAxes(true, true, 1.0, 1.05);
99-
this->replot();
98+
rescaleAxes(true, true, 1.0, 1.05);
99+
replot();
100+
}
101+
102+
void HeightPlotView::setNodesVisible(bool visible) {
103+
graphPoints->setVisible(visible);
104+
graphSelected->setVisible(visible);
100105
}

gui/source/pre/views/limb2d/HeightPlotView.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ class QCPGraph;
77
class HeightPlotView: public PlotWidget {
88
public:
99
HeightPlotView(MainModel* model, QPersistentModelIndex index);
10-
void updatePlot();
1110

1211
private:
1312
MainModel* model;
@@ -16,4 +15,7 @@ class HeightPlotView: public PlotWidget {
1615
QCPGraph* graphLine;
1716
QCPGraph* graphPoints;
1817
QCPGraph* graphSelected;
18+
19+
void updatePlot();
20+
void setNodesVisible(bool visible);
1921
};

gui/source/pre/views/limb2d/ProfilePlotView.cpp

Lines changed: 51 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
#include "pre/models/MainModel.hpp"
33
#include "pre/models/units/UnitSystem.hpp"
44

5-
// Magic numbers
6-
const size_t N_SEGMENT_POINTS = 100;
7-
const size_t N_CURVATURE_POINTS = 200;
5+
// Magic number, determines offset of the curvature outline (fraction of curve length)
86
const double CURVATURE_SCALING = 0.05;
97

108
ProfilePlotView::ProfilePlotView(MainModel* model):
@@ -18,16 +16,17 @@ ProfilePlotView::ProfilePlotView(MainModel* model):
1816
curveLine->setPen({Qt::blue, 2});
1917

2018
// 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);
19+
curveNodes = new QCPCurve(this->xAxis, this->yAxis);
20+
curveNodes->setName("Points");
21+
curveNodes->setScatterStyle({QCPScatterStyle::ssSquare, Qt::blue, 8});
22+
curveNodes->setLineStyle(QCPCurve::lsNone);
23+
24+
// Curvature visualization
25+
curvatureOutline = new QCPCurve(this->xAxis, this->yAxis);
26+
curvatureOutline->setName("Curvature outline");
27+
curvatureOutline->setPen(Qt::NoPen);
28+
curvatureOutline->setBrush(QBrush(QColor(0, 0, 255, 35)));
29+
curvatureOutline->setScatterSkip(0);
3130

3231
// Menu actions
3332

@@ -36,24 +35,21 @@ ProfilePlotView::ProfilePlotView(MainModel* model):
3635
action_show_curvature->setChecked(false);
3736
QObject::connect(action_show_curvature, &QAction::triggered, [&] {
3837
updateVisibility();
39-
this->replot();
38+
replot();
4039
});
4140

4241
action_show_nodes = new QAction("Show nodes", this);
4342
action_show_nodes->setCheckable(true);
4443
action_show_nodes->setChecked(true);
4544
QObject::connect(action_show_nodes, &QAction::triggered, [&] {
4645
updateVisibility();
47-
this->replot();
46+
replot();
4847
});
4948

50-
QAction* before = this->contextMenu()->actions().isEmpty() ? nullptr : this->contextMenu()->actions().front();
51-
this->contextMenu()->insertAction(before, action_show_curvature);
52-
this->contextMenu()->insertAction(before, action_show_nodes);
53-
this->contextMenu()->insertSeparator(before);
54-
55-
// Update on unit changes
56-
//QObject::connect(&quantity, &Quantity::unitChanged, this, &ProfilePlotView::updatePlot);
49+
QAction* before = contextMenu()->actions().isEmpty() ? nullptr : contextMenu()->actions().front();
50+
contextMenu()->insertAction(before, action_show_curvature);
51+
contextMenu()->insertAction(before, action_show_nodes);
52+
contextMenu()->insertSeparator(before);
5753

5854
// Update on unit and geometry changes
5955
QObject::connect(&Quantities::length, &Quantity::unitChanged, this, &ProfilePlotView::updatePlot);
@@ -63,138 +59,59 @@ ProfilePlotView::ProfilePlotView(MainModel* model):
6359
updatePlot();
6460
}
6561

66-
/*
67-
void ProfilePlotView::setData(const Profile& data) {
68-
input = data;
69-
updatePlot();
70-
}
71-
72-
void ProfilePlotView::setSelection(const QList<int>& indices) {
73-
selection = indices;
74-
updateSelection();
75-
this->replot();
76-
}
77-
*/
78-
7962
void ProfilePlotView::updatePlot() {
8063
this->xAxis->setLabel("X " + Quantities::length.getUnit().getLabel());
8164
this->yAxis->setLabel("Y " + Quantities::length.getUnit().getLabel());
8265

8366
curveLine->data()->clear();
84-
curvePoints->data()->clear();
85-
curveSelected->data()->clear();
67+
curveNodes->data()->clear();
68+
curvatureOutline->data()->clear();
69+
8670

8771
if(model->hasGeometry()) {
72+
auto& position = model->getGeometry().position_eval;
73+
auto& curvature = model->getGeometry().curvature_eval;
74+
75+
// Determine scaling of the curvature outline from curve length and maximum curvature
76+
double k_max = *std::max_element(curvature.begin(), curvature.end(), [](double a, double b){ return std::abs(a) < std::abs(b); });
77+
double scale = (k_max != 0.0) ? CURVATURE_SCALING*model->getGeometry().length.back()/std::abs(k_max) : 0.0;
78+
79+
// Plot outline of the curvature curve
80+
for(size_t i = 0; i < position.size(); ++i) {
81+
curvatureOutline->addData(
82+
Quantities::length.getUnit().fromBase(position[i][0] - scale*curvature[i]*sin(position[i][2])),
83+
Quantities::length.getUnit().fromBase(position[i][1] + scale*curvature[i]*cos(position[i][2]))
84+
);
85+
}
86+
87+
// Close the loop by adding the profile curve points
88+
for(int i = static_cast<int>(position.size()) - 1; i >= 0; --i) {
89+
curvatureOutline->addData(
90+
Quantities::length.getUnit().fromBase(position[i][0]),
91+
Quantities::length.getUnit().fromBase(position[i][1])
92+
);
93+
}
94+
95+
// Plot profile curve
8896
for(auto& point: model->getGeometry().position_eval) {
8997
curveLine->addData(
9098
Quantities::length.getUnit().fromBase(point[0]),
9199
Quantities::length.getUnit().fromBase(point[1])
92100
);
93101
}
94102

103+
// Plot profile nodes
95104
for(auto& point: model->getGeometry().position_control) {
96-
curvePoints->addData(
105+
curveNodes->addData(
97106
Quantities::length.getUnit().fromBase(point[0]),
98107
Quantities::length.getUnit().fromBase(point[1])
99108
);
100109
}
101110
}
102111

103-
this->rescaleAxes();
104-
this->replot();
105-
106-
/*
107-
// Construct profile curve segment by segment, stop on first error
108-
ProfileCurve profile;
109-
try {
110-
for(auto& segment: input.segments) {
111-
profile.add_segment(segment);
112-
}
113-
}
114-
catch(const std::exception& e) {
115-
// TODO: Show error on plot
116-
}
117-
118-
// Abort the curve is empty, otherwise draw the correct segments
119-
if(profile.get_segments().empty()) {
120-
return;
121-
}
122-
123-
// Add curvature
124-
std::vector<double> s = linspace(0.0, profile.length(), N_CURVATURE_POINTS);
125-
std::vector<double> k; k.reserve(s.size());
126-
for(double si: s) {
127-
k.push_back(profile.curvature(si));
128-
}
129-
130-
double k_max = *std::max_element(k.begin(), k.end(), [](double a, double b){ return std::abs(a) < std::abs(b); });
131-
double scale = (k_max != 0.0) ? CURVATURE_SCALING*profile.length()/std::abs(k_max) : 0.0;
132-
133-
auto curvature_outline = new QCPCurve(this->xAxis, this->yAxis);
134-
curvature_outline->setName("Curvature outline");
135-
curvature_outline->setPen({Qt::darkGray, 1});
136-
curvature_outline->setScatterSkip(0);
137-
138-
curvature_lines.clear();
139-
curvature_lines.push_back(curvature_outline);
140-
141-
for(size_t i = 0; i < s.size(); ++i) {
142-
Vector<2> position = profile.position(s[i]);
143-
double angle = profile.angle(s[i]);
144-
145-
double x_start = quantity.getUnit().fromBase(position(0));
146-
double y_start = quantity.getUnit().fromBase(position(1));
147-
double x_end = quantity.getUnit().fromBase(position(0) - scale*k[i]*sin(angle));
148-
double y_end = quantity.getUnit().fromBase(position(1) + scale*k[i]*cos(angle));
149-
150-
auto line = new QCPCurve(this->xAxis, this->yAxis);
151-
line->setPen({Qt::lightGray, 1});
152-
line->setScatterSkip(0);
153-
line->addData(x_start, y_start);
154-
line->addData(x_end, y_end);
155-
156-
curvature_outline->addData(x_end, y_end);
157-
curvature_lines.push_back(line);
158-
}
159-
160-
// Add profile segments
161-
segment_curves.clear();
162-
for(size_t i = 0; i < profile.get_nodes().size()-1; ++i) {
163-
auto segment_curve = new QCPCurve(this->xAxis, this->yAxis);
164-
segment_curve->setName("Segment");
165-
segment_curves.push_back(segment_curve);
166-
167-
for(double s: Linspace<double>(profile.get_nodes()[i].s, profile.get_nodes()[i+1].s, N_SEGMENT_POINTS)) {
168-
Vector<2> point = profile.position(s);
169-
segment_curve->addData(
170-
quantity.getUnit().fromBase(point(0)),
171-
quantity.getUnit().fromBase(point(1))
172-
);
173-
}
174-
}
175-
176-
// Add profile nodes
177-
segment_nodes.clear();
178-
179-
std::vector<Point> nodes;
180-
for(auto& segment: profile.get_segments()) {
181-
std::vector<Point> segment_nodes = segment->nodes();
182-
nodes.insert(nodes.end(), segment_nodes.begin(), segment_nodes.end());
183-
}
184-
185-
for(auto& node: nodes) {
186-
auto segment_node = new QCPCurve(this->xAxis, this->yAxis);
187-
segment_node->setName("Node");
188-
segment_nodes.push_back(segment_node);
189-
segment_node->addData(
190-
quantity.getUnit().fromBase(node.position(0)),
191-
quantity.getUnit().fromBase(node.position(1))
192-
);
193-
}
194-
195-
updateSelection();
196112
updateVisibility();
197-
*/
113+
rescaleAxes();
114+
replot();
198115
}
199116

200117
void ProfilePlotView::updateSelection() {
@@ -226,13 +143,6 @@ void ProfilePlotView::updateSelection() {
226143
}
227144

228145
void ProfilePlotView::updateVisibility() {
229-
/*
230-
for(auto line: curvature_lines) {
231-
line->setVisible(action_show_curvature->isChecked());
232-
}
233-
234-
for(auto segment_node: segment_nodes) {
235-
segment_node->setVisible(action_show_nodes->isChecked());
236-
}
237-
*/
146+
curveNodes->setVisible(action_show_nodes->isChecked());
147+
curvatureOutline->setVisible(action_show_curvature->isChecked());
238148
}

gui/source/pre/views/limb2d/ProfilePlotView.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ class ProfilePlotView: public PlotWidget
1919
QAction* action_show_nodes;
2020

2121
QCPCurve* curveLine;
22-
QCPCurve* curvePoints;
23-
QCPCurve* curveSelected;
22+
QCPCurve* curveNodes;
23+
QCPCurve* curvatureOutline;
2424

2525
void updatePlot();
2626
void updateSelection();
2727
void updateVisibility();
2828

29-
//void setCurvatureVisible(bool visible);
30-
//void setNodesVisible(bool visible);
29+
void setCurvatureVisible(bool visible);
30+
void setNodesVisible(bool visible);
3131
};

gui/source/pre/views/limb2d/WidthPlotView.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ WidthPlotView::WidthPlotView(MainModel* model):
2626
action_show_nodes->setCheckable(true);
2727
action_show_nodes->setChecked(true);
2828
QObject::connect(action_show_nodes, &QAction::triggered, [&](bool checked) {
29-
//setNodesVisible(checked);
29+
setNodesVisible(checked);
3030
replot();
3131
});
3232

@@ -83,6 +83,11 @@ void WidthPlotView::updatePlot() {
8383
}
8484
}
8585

86-
this->rescaleAxes(true, true, 1.0, 1.05);
87-
this->replot();
86+
rescaleAxes(true, true, 1.0, 1.05);
87+
replot();
88+
}
89+
90+
void WidthPlotView::setNodesVisible(bool visible) {
91+
graphPoints->setVisible(visible);
92+
graphSelected->setVisible(visible);
8893
}

gui/source/pre/views/limb2d/WidthPlotView.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ class QCPGraph;
77
class WidthPlotView: public PlotWidget {
88
public:
99
WidthPlotView(MainModel* model);
10-
void updatePlot();
1110

1211
private:
1312
MainModel* model;
1413
QCPGraph* graphLine;
1514
QCPGraph* graphPoints;
1615
QCPGraph* graphSelected;
16+
17+
void updatePlot();
18+
void setNodesVisible(bool visible);
1719
};

gui/source/solver/BowResult.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct LimbInfo {
4747
std::vector<double> length;
4848
std::vector<std::array<double, 3>> position_eval;
4949
std::vector<std::array<double, 3>> position_control;
50+
std::vector<double> curvature_eval;
5051
std::vector<double> width;
5152
std::vector<double> height;
5253
std::vector<std::vector<double>> bounds;
@@ -62,6 +63,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(
6263
length,
6364
position_eval,
6465
position_control,
66+
curvature_eval,
6567
width,
6668
height,
6769
bounds,

0 commit comments

Comments
 (0)