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>
2528#include < QtMath>
2629#include < QCheckBox>
3235#include < QSpinBox>
3336#include < QWidget>
3437
38+ #include " core/map.h"
3539#include " core/map_coord.h"
3640#include " core/path_coord.h"
3741#include " core/symbols/point_symbol.h"
3842#include " core/objects/object.h"
3943#include " gui/util_gui.h"
44+ #include " undo/object_undo.h"
4045
4146
4247namespace OpenOrienteering {
4348
44- bool DistributePointsTool::showSettingsDialog (
45- QWidget* parent,
46- const PointSymbol* point,
47- DistributePointsTool::Settings& settings )
49+ DistributePointsDialog::DistributePointsDialog (QWidget* parent, Map* map, const PointSymbol* point)
50+ : QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint)
51+ , map { map }
52+ , point { point }
53+ {
54+ setWindowTitle (tr (" Distribute points evenly along path" ));
55+
56+ auto layout = new QFormLayout ();
57+
58+ num_points_edit = Util::SpinBox::create (1 , 9999 );
59+ num_points_edit->setValue (3 );
60+ layout->addRow (tr (" Number of points per path:" ), num_points_edit);
61+
62+ points_at_ends_check = new QCheckBox (tr (" Also place objects at line end points" ));
63+ points_at_ends_check->setChecked (true );
64+ layout->addRow (points_at_ends_check);
65+
66+ layout->addItem (Util::SpacerItem::create (this ));
67+
68+ auto rotation_headline = Util::Headline::create (tr (" Rotation settings" ));
69+ layout->addRow (rotation_headline);
70+
71+ rotate_symbols_check = new QCheckBox (tr (" Align points with direction of line" ));
72+ rotate_symbols_check->setChecked (true );
73+ layout->addRow (rotate_symbols_check);
74+
75+ additional_rotation_edit = Util::SpinBox::create<Util::RotationalDegrees>();
76+ additional_rotation_edit->setDecimals (1 );
77+ additional_rotation_edit->setSingleStep (5.0 );
78+ additional_rotation_edit->setValue (qRadiansToDegrees (0.0 ));
79+ layout->addRow (tr (" Additional rotation angle (counter-clockwise):" ), additional_rotation_edit);
80+
81+ if (!point->isRotatable ())
82+ {
83+ rotation_headline->setEnabled (false );
84+ rotate_symbols_check->setEnabled (false );
85+ additional_rotation_edit->setEnabled (false );
86+ layout->labelForField (additional_rotation_edit)->setEnabled (false );
87+ }
88+
89+ layout->addItem (Util::SpacerItem::create (this ));
90+ auto button_box = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
91+ layout->addRow (button_box);
92+
93+ setLayout (layout);
94+
95+ connect (button_box, &QDialogButtonBox::accepted, this , &DistributePointsDialog::okClicked);
96+ connect (button_box, &QDialogButtonBox::rejected, this , &QDialog::reject);
97+ }
98+
99+ DistributePointsDialog::~DistributePointsDialog () = default ;
100+
101+ // slot
102+ void DistributePointsDialog::okClicked ()
48103{
49- DistributePointsSettingsDialog dialog (parent, point, settings);
50- dialog.setWindowModality (Qt::WindowModal);
51- if (dialog.exec () == QDialog::Rejected)
52- return false ;
104+ // Create points along paths
105+ created_objects.reserve (map->selectedObjects ().size () * num_points_edit->value ());
106+ for (const auto * object : map->selectedObjects ())
107+ {
108+ if (object->getType () == Object::Path)
109+ distributePoints (object->asPath ());
110+ }
111+ if (created_objects.empty ())
112+ return ;
113+
114+ // Add points to map
115+ for (auto * o : created_objects)
116+ map->addObject (o);
117+
118+ // Create undo step and select new objects
119+ map->clearObjectSelection (false );
120+ MapPart* part = map->getCurrentPart ();
121+ auto * delete_step = new DeleteObjectsUndoStep (map);
122+ for (std::size_t i = 0 ; i < created_objects.size (); ++i)
123+ {
124+ Object* object = created_objects[i];
125+ delete_step->addObject (part->findObjectIndex (object));
126+ map->addObjectToSelection (object, i == created_objects.size () - 1 );
127+ }
128+ map->push (delete_step);
129+ map->setObjectsDirty ();
53130
54- dialog.getValues (settings);
55- return true ;
131+ accept ();
56132}
57133
58- void DistributePointsTool::execute (
59- const PathObject* path,
60- PointSymbol* point,
61- const DistributePointsTool::Settings& settings,
62- std::vector<PointObject*>& out_objects )
134+ void DistributePointsDialog::distributePoints (const PathObject* path)
63135{
136+ const auto num_points_per_line = num_points_edit->value ();
137+ const auto points_at_ends = points_at_ends_check->isChecked ();
138+ const auto rotate_symbols = rotate_symbols_check->isChecked ();
139+ const auto additional_rotation = qDegreesToRadians (additional_rotation_edit->value ());
140+
64141 path->update ();
65142
66143 // This places the points only on the first part.
@@ -70,25 +147,25 @@ void DistributePointsTool::execute(
70147 int total, start, end;
71148 if (part.isClosed ())
72149 {
73- total = settings. num_points_per_line ;
150+ total = num_points_per_line;
74151 start = 0 ;
75152 end = total - 1 ;
76153 }
77- else if (!settings. points_at_ends )
154+ else if (!points_at_ends)
78155 {
79- total = settings. num_points_per_line + 1 ;
156+ total = num_points_per_line + 1 ;
80157 start = 1 ;
81158 end = total - 1 ;
82159 }
83- else if (settings. num_points_per_line == 1 )
160+ else if (num_points_per_line == 1 )
84161 {
85162 total = 1 ;
86163 start = 1 ;
87164 end = 1 ;
88165 }
89166 else
90167 {
91- total = settings. num_points_per_line - 1 ;
168+ total = num_points_per_line - 1 ;
92169 start = 0 ;
93170 end = total;
94171 }
@@ -106,77 +183,17 @@ void DistributePointsTool::execute(
106183 object->setPosition (split.pos );
107184 if (point->isRotatable ())
108185 {
109- double rotation = settings. additional_rotation ;
110- if (settings. rotate_symbols )
186+ double rotation = additional_rotation;
187+ if (rotate_symbols)
111188 {
112189 auto right = split.tangentVector ().perpRight ();
113190 rotation -= right.angle ();
114191 }
115192 object->setRotation (rotation);
116193 }
117- out_objects .push_back (object);
194+ created_objects .push_back (object);
118195 }
119196}
120197
121198
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-
182199} // namespace OpenOrienteering
0 commit comments