11/*
22 * Copyright 2013 Thomas Schöps
3- * Copyright 2014, 2015 Kai Pastor
3+ * Copyright 2014-2015, 2017-2019 Kai Pastor
4+ * Copyright 2024 Matthias Kühlewein
45 *
56 * This file is part of OpenOrienteering.
67 *
2122
2223#include " distribute_points_tool.h"
2324
25+ #include < vector>
26+
2427#include < Qt>
25- #include < QtMath>
2628#include < QCheckBox>
2729#include < QDialogButtonBox>
2830#include < QDoubleSpinBox>
3234#include < QSpinBox>
3335#include < QWidget>
3436
37+ #include " core/map.h"
3538#include " core/map_coord.h"
3639#include " core/path_coord.h"
3740#include " core/symbols/point_symbol.h"
3841#include " core/objects/object.h"
3942#include " gui/util_gui.h"
43+ #include " undo/object_undo.h"
4044
4145
4246namespace OpenOrienteering {
4347
44- bool DistributePointsTool::showSettingsDialog (
45- QWidget* parent,
46- const PointSymbol* point,
47- DistributePointsTool::Settings& settings )
48+ DistributePointsDialog::DistributePointsDialog (QWidget* parent, Map* map, const PointSymbol* point)
49+ : QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint)
50+ , map { map }
51+ , point { point }
52+ {
53+ setWindowTitle (tr (" Distribute points evenly along path" ));
54+
55+ auto layout = new QFormLayout ();
56+
57+ num_points_edit = Util::SpinBox::create (1 , 9999 );
58+ num_points_edit->setValue (3 );
59+ layout->addRow (tr (" Number of points per path:" ), num_points_edit);
60+
61+ points_at_ends_check = new QCheckBox (tr (" Also place objects at line end points" ));
62+ points_at_ends_check->setChecked (true );
63+ layout->addRow (points_at_ends_check);
64+
65+ layout->addItem (Util::SpacerItem::create (this ));
66+
67+ auto rotation_headline = Util::Headline::create (tr (" Rotation settings" ));
68+ layout->addRow (rotation_headline);
69+
70+ rotate_symbols_check = new QCheckBox (tr (" Align points with direction of line" ));
71+ rotate_symbols_check->setChecked (true );
72+ layout->addRow (rotate_symbols_check);
73+
74+ additional_rotation_edit = Util::SpinBox::create<Util::RotationalDegrees>();
75+ additional_rotation_edit->setDecimals (1 );
76+ additional_rotation_edit->setSingleStep (5.0 );
77+ additional_rotation_edit->setValue (qRadiansToDegrees (0.0 ));
78+ layout->addRow (tr (" Additional rotation angle (counter-clockwise):" ), additional_rotation_edit);
79+
80+ if (!point->isRotatable ())
81+ {
82+ rotation_headline->setEnabled (false );
83+ rotate_symbols_check->setEnabled (false );
84+ additional_rotation_edit->setEnabled (false );
85+ layout->labelForField (additional_rotation_edit)->setEnabled (false );
86+ }
87+
88+ layout->addItem (Util::SpacerItem::create (this ));
89+ auto button_box = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
90+ layout->addRow (button_box);
91+
92+ setLayout (layout);
93+
94+ connect (button_box, &QDialogButtonBox::accepted, this , &DistributePointsDialog::okClicked);
95+ connect (button_box, &QDialogButtonBox::rejected, this , &QDialog::reject);
96+ }
97+
98+ DistributePointsDialog::~DistributePointsDialog () = default ;
99+
100+ // slot
101+ void DistributePointsDialog::okClicked ()
48102{
49- DistributePointsSettingsDialog dialog (parent, point, settings);
50- dialog.setWindowModality (Qt::WindowModal);
51- if (dialog.exec () == QDialog::Rejected)
52- return false ;
103+ // Create points along paths
104+ created_objects.reserve (map->selectedObjects ().size () * num_points_edit->value ());
105+ for (const auto * object : map->selectedObjects ())
106+ {
107+ if (object->getType () == Object::Path)
108+ distributePoints (object->asPath ());
109+ }
110+ if (created_objects.empty ())
111+ return ;
112+
113+ // Add points to map
114+ for (auto * o : created_objects)
115+ map->addObject (o);
116+
117+ // Create undo step and select new objects
118+ map->clearObjectSelection (false );
119+ MapPart* part = map->getCurrentPart ();
120+ auto * delete_step = new DeleteObjectsUndoStep (map);
121+ for (std::size_t i = 0 ; i < created_objects.size (); ++i)
122+ {
123+ Object* object = created_objects[i];
124+ delete_step->addObject (part->findObjectIndex (object));
125+ map->addObjectToSelection (object, i == created_objects.size () - 1 );
126+ }
127+ map->push (delete_step);
128+ map->setObjectsDirty ();
53129
54- dialog.getValues (settings);
55- return true ;
130+ accept ();
56131}
57132
58- void DistributePointsTool::execute (
59- const PathObject* path,
60- PointSymbol* point,
61- const DistributePointsTool::Settings& settings,
62- std::vector<PointObject*>& out_objects )
133+ void DistributePointsDialog::distributePoints (const PathObject* path)
63134{
135+ const auto num_points_per_line = num_points_edit->value ();
136+ const auto points_at_ends = points_at_ends_check->isChecked ();
137+ const auto rotate_symbols = rotate_symbols_check->isChecked ();
138+ const auto additional_rotation = qDegreesToRadians (additional_rotation_edit->value ());
139+
64140 path->update ();
65141
66142 // This places the points only on the first part.
@@ -70,25 +146,25 @@ void DistributePointsTool::execute(
70146 int total, start, end;
71147 if (part.isClosed ())
72148 {
73- total = settings. num_points_per_line ;
149+ total = num_points_per_line;
74150 start = 0 ;
75151 end = total - 1 ;
76152 }
77- else if (!settings. points_at_ends )
153+ else if (!points_at_ends)
78154 {
79- total = settings. num_points_per_line + 1 ;
155+ total = num_points_per_line + 1 ;
80156 start = 1 ;
81157 end = total - 1 ;
82158 }
83- else if (settings. num_points_per_line == 1 )
159+ else if (num_points_per_line == 1 )
84160 {
85161 total = 1 ;
86162 start = 1 ;
87163 end = 1 ;
88164 }
89165 else
90166 {
91- total = settings. num_points_per_line - 1 ;
167+ total = num_points_per_line - 1 ;
92168 start = 0 ;
93169 end = total;
94170 }
@@ -106,77 +182,17 @@ void DistributePointsTool::execute(
106182 object->setPosition (split.pos );
107183 if (point->isRotatable ())
108184 {
109- double rotation = settings. additional_rotation ;
110- if (settings. rotate_symbols )
185+ double rotation = additional_rotation;
186+ if (rotate_symbols)
111187 {
112188 auto right = split.tangentVector ().perpRight ();
113189 rotation -= right.angle ();
114190 }
115191 object->setRotation (rotation);
116192 }
117- out_objects .push_back (object);
193+ created_objects .push_back (object);
118194 }
119195}
120196
121197
122- DistributePointsSettingsDialog::DistributePointsSettingsDialog (
123- QWidget* parent,
124- const PointSymbol* point,
125- const DistributePointsTool::Settings& settings )
126- : QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint)
127- {
128- setWindowTitle (tr (" Distribute points evenly along path" ));
129-
130- auto layout = new QFormLayout ();
131-
132- num_points_edit = Util::SpinBox::create (1 , 9999 );
133- num_points_edit->setValue (settings.num_points_per_line );
134- layout->addRow (tr (" Number of points per path:" ), num_points_edit);
135-
136- points_at_ends_check = new QCheckBox (tr (" Also place objects at line end points" ));
137- points_at_ends_check->setChecked (settings.points_at_ends );
138- layout->addRow (points_at_ends_check);
139-
140- layout->addItem (Util::SpacerItem::create (this ));
141-
142- auto rotation_headline = Util::Headline::create (tr (" Rotation settings" ));
143- layout->addRow (rotation_headline);
144-
145- rotate_symbols_check = new QCheckBox (tr (" Align points with direction of line" ));
146- rotate_symbols_check->setChecked (settings.rotate_symbols );
147- layout->addRow (rotate_symbols_check);
148-
149- additional_rotation_edit = Util::SpinBox::create<Util::RotationalDegrees>();
150- additional_rotation_edit->setDecimals (1 );
151- additional_rotation_edit->setSingleStep (5.0 );
152- additional_rotation_edit->setValue (qRadiansToDegrees (settings.additional_rotation ));
153- layout->addRow (tr (" Additional rotation angle (counter-clockwise):" ), additional_rotation_edit);
154-
155- if (!point->isRotatable ())
156- {
157- rotation_headline->setEnabled (false );
158- rotate_symbols_check->setEnabled (false );
159- additional_rotation_edit->setEnabled (false );
160- layout->labelForField (additional_rotation_edit)->setEnabled (false );
161- }
162-
163- layout->addItem (Util::SpacerItem::create (this ));
164- auto button_box = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal);
165- layout->addRow (button_box);
166-
167- setLayout (layout);
168-
169- connect (button_box, &QDialogButtonBox::accepted, this , &QDialog::accept);
170- connect (button_box, &QDialogButtonBox::rejected, this , &QDialog::reject);
171- }
172-
173- void DistributePointsSettingsDialog::getValues (DistributePointsTool::Settings& settings)
174- {
175- settings.num_points_per_line = num_points_edit->value ();
176- settings.points_at_ends = points_at_ends_check->isChecked ();
177- settings.rotate_symbols = rotate_symbols_check->isChecked ();
178- settings.additional_rotation = qDegreesToRadians (additional_rotation_edit->value ());
179- }
180-
181-
182198} // namespace OpenOrienteering
0 commit comments