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)
86const double CURVATURE_SCALING = 0.05 ;
97
108ProfilePlotView::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-
7962void 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
200117void ProfilePlotView::updateSelection () {
@@ -226,13 +143,6 @@ void ProfilePlotView::updateSelection() {
226143}
227144
228145void 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}
0 commit comments