Skip to content

Commit 587cdeb

Browse files
authored
SCM Plugin: Option to merge constellation lines into polylines (Stellarium#4563)
* implement mergeLinesIntoPolylines function * do not create working copy * [skip ci] update changelog * increase code readability
1 parent 399c656 commit 587cdeb

File tree

8 files changed

+133
-7
lines changed

8 files changed

+133
-7
lines changed

plugins/SkyCultureMaker/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Version 1.0.1
44

5+
* New Feature: Option to automatically merge lines into polylines on export
56
* Fix: Drawn constellations are not reset after "Export and Exit"
67
* Fix: "Export and Exit" exits even when export failed, deleting all unsaved progress
78
* Fix: Stop drawing line key (Double Right Click) only works when Star/DSO is selected

plugins/SkyCultureMaker/src/ScmConstellation.cpp

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ void scm::ScmConstellation::drawNames(StelCore *core, StelPainter &sPainter) con
188188
drawNames(core, sPainter, defaultConstellationNameColor);
189189
}
190190

191-
QJsonObject scm::ScmConstellation::toJson(const QString &skyCultureId) const
191+
QJsonObject scm::ScmConstellation::toJson(const QString &skyCultureId, const bool mergeLines) const
192192
{
193193
QJsonObject json;
194194

@@ -212,6 +212,11 @@ QJsonObject scm::ScmConstellation::toJson(const QString &skyCultureId) const
212212
}
213213
}
214214

215+
if (mergeLines)
216+
{
217+
mergeLinesIntoPolylines(linesArray);
218+
}
219+
215220
json["id"] = "CON " + skyCultureId + " " + id;
216221
json["lines"] = linesArray;
217222
if (artwork.getHasArt() && !artworkPath.isEmpty())
@@ -284,3 +289,82 @@ void scm::ScmConstellation::show()
284289
{
285290
isHidden = false;
286291
}
292+
293+
void scm::ScmConstellation::mergeLinesIntoPolylines(QJsonArray &lines) const
294+
{
295+
if (lines.size() < 2)
296+
{
297+
// Nothing to merge
298+
return;
299+
}
300+
301+
// Step 1: merge line ends with other line starts
302+
for (int growableLineIdx = 0; growableLineIdx < lines.size(); ++growableLineIdx)
303+
{
304+
QJsonArray growableLine = lines.at(growableLineIdx).toArray();
305+
306+
// Look for a line that starts where the growableLine ends
307+
for (int attachableLineIdx = growableLineIdx + 1; attachableLineIdx < lines.size(); ++attachableLineIdx)
308+
{
309+
QJsonArray attachableLine = lines.at(attachableLineIdx).toArray();
310+
311+
// Merge attachableLine into growableLine
312+
if (growableLine.last() == attachableLine.first())
313+
{
314+
// Append all points from attachableLine except the first (which is duplicate)
315+
attachableLine.removeFirst();
316+
for (QJsonValue attachableLinePoint : attachableLine)
317+
{
318+
growableLine.append(attachableLinePoint);
319+
}
320+
321+
// Update the merged lines array
322+
lines[growableLineIdx] = growableLine;
323+
lines.removeAt(attachableLineIdx);
324+
325+
// Recheck the merged line
326+
--growableLineIdx;
327+
// Reset j to growableLineIdx + 1 to continue merging
328+
attachableLineIdx = growableLineIdx + 1;
329+
break;
330+
}
331+
}
332+
}
333+
334+
// Step 2: merge line starts with other line ends
335+
for (int growableLineIdx = 0; growableLineIdx < lines.size(); ++growableLineIdx)
336+
{
337+
QJsonArray growableLine = lines.at(growableLineIdx).toArray();
338+
339+
// Look for a line that ends where the growableLine starts
340+
for (int attachableLineIdx = growableLineIdx + 1; attachableLineIdx < lines.size(); ++attachableLineIdx)
341+
{
342+
QJsonArray attachableLine = lines.at(attachableLineIdx).toArray();
343+
344+
if (growableLine.first() == attachableLine.last())
345+
{
346+
QJsonArray newGrowableLine;
347+
// Prepend all points from attachableLine except the last (which is duplicate)
348+
attachableLine.removeLast();
349+
for (QJsonValue attachableLinePoint : attachableLine)
350+
{
351+
newGrowableLine.append(attachableLinePoint);
352+
}
353+
for (QJsonValue growableLinePoint : growableLine)
354+
{
355+
newGrowableLine.append(growableLinePoint);
356+
}
357+
growableLine = newGrowableLine;
358+
359+
lines[growableLineIdx] = growableLine;
360+
lines.removeAt(attachableLineIdx);
361+
362+
// Recheck the merged line
363+
--growableLineIdx;
364+
// Reset j to growableLineIdx + 1 to continue merging
365+
attachableLineIdx = growableLineIdx + 1;
366+
break;
367+
}
368+
}
369+
}
370+
}

plugins/SkyCultureMaker/src/ScmConstellation.hpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,10 @@ class ScmConstellation
183183
* @brief Returns the constellation data as a JSON object.
184184
*
185185
* @param skyCultureId The ID of the sky culture to which this constellation belongs.
186+
* @param mergeLines Whether to merge lines into polylines where possible.
186187
* @return QJsonObject
187188
*/
188-
QJsonObject toJson(const QString &skyCultureId) const;
189+
QJsonObject toJson(const QString &skyCultureId, const bool mergeLines) const;
189190

190191
/**
191192
* @brief Saves the artwork of this constellation, if art is attached, to the give filepath.
@@ -266,6 +267,28 @@ class ScmConstellation
266267
* @brief Updates the XYZname that is used for the text position.
267268
*/
268269
void updateTextPosition();
270+
271+
/**
272+
* @brief Merges individual star lines into polylines where possible.
273+
*
274+
* Merging is done in a two step process, where first the ends of lines are merged
275+
* with the starts of other lines if they match, and secondly the starts of lines are
276+
* merged with the ends of other lines if they match. The lines are processed in the order
277+
* they have been drawn. However, lines which point to opposite directions are not merged.
278+
*
279+
* Example:
280+
*
281+
* Input 1: [[1,2], [2,3], [0,1]]
282+
*
283+
* Output 1: [[0,1,2,3]]
284+
*
285+
* Input 2: [[1,2], [2,3], [1,0]]
286+
*
287+
* Output 2: [[1,2,3], [1,0]]
288+
*
289+
* @param lines The individual star lines to merge.
290+
*/
291+
void mergeLinesIntoPolylines(QJsonArray &lines) const;
269292
};
270293

271294
} // namespace scm

plugins/SkyCultureMaker/src/ScmSkyCulture.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ std::vector<scm::ScmConstellation> *scm::ScmSkyCulture::getConstellations()
6767
return &constellations;
6868
}
6969

70-
QJsonObject scm::ScmSkyCulture::toJson() const
70+
QJsonObject scm::ScmSkyCulture::toJson(const bool mergeLines) const
7171
{
7272
QJsonObject scJsonObj;
7373
scJsonObj["id"] = id;
@@ -79,7 +79,7 @@ QJsonObject scm::ScmSkyCulture::toJson() const
7979
QJsonArray constellationsArray;
8080
for (const auto &constellation : constellations)
8181
{
82-
constellationsArray.append(constellation.toJson(id));
82+
constellationsArray.append(constellation.toJson(id, mergeLines));
8383
}
8484
scJsonObj["constellations"] = constellationsArray;
8585

plugins/SkyCultureMaker/src/ScmSkyCulture.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,10 @@ class ScmSkyCulture
6969

7070
/**
7171
* @brief Returns the sky culture as a JSON object
72+
*
73+
* @param mergeLines Whether to merge the lines of the constellations into polylines where possible.
7274
*/
73-
QJsonObject toJson() const;
75+
QJsonObject toJson(const bool mergeLines) const;
7476

7577
/**
7678
* @brief Draws the sky culture.

plugins/SkyCultureMaker/src/SkyCultureMaker.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ SkyCultureMaker::SkyCultureMaker()
9494
initSetting(conf, "floatingLineColor", "1.0,0.7,0.7");
9595
initSetting(conf, "floatingLineAlpha", 0.5);
9696
initSetting(conf, "maxSnapRadiusInPixels", 25);
97+
initSetting(conf, "mergeLinesOnExport", true);
9798

9899
conf->endGroup();
99100
}

plugins/SkyCultureMaker/src/gui/ScmSkyCultureExportDialog.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ void ScmSkyCultureExportDialog::createDialogContent()
6969
connect(&StelApp::getInstance(), SIGNAL(languageChanged()), this, SLOT(retranslate()));
7070
connect(ui->titleBar, SIGNAL(movedTo(QPoint)), this, SLOT(handleMovedTo(QPoint)));
7171
connect(ui->titleBar, &TitleBar::closeClicked, this, &ScmSkyCultureExportDialog::close);
72+
73+
ui->mergeLinesCB->setChecked(
74+
StelApp::getInstance().getSettings()->value("SkyCultureMaker/mergeLinesOnExport", true).toBool());
75+
connect(ui->mergeLinesCB, &QCheckBox::toggled, this, [](bool checked)
76+
{ StelApp::getInstance().getSettings()->setValue("SkyCultureMaker/mergeLinesOnExport", checked); });
77+
7278
connect(ui->exportBtn, &QPushButton::clicked, this, &ScmSkyCultureExportDialog::exportSkyCulture);
7379
connect(ui->exportAndExitBtn, &QPushButton::clicked, this, &ScmSkyCultureExportDialog::exportAndExitSkyCulture);
7480
connect(ui->cancelBtn, &QPushButton::clicked, this, &ScmSkyCultureExportDialog::close);
@@ -146,8 +152,10 @@ bool ScmSkyCultureExportDialog::exportSkyCulture()
146152
}
147153

148154
// Export the sky culture to the index.json file
149-
qDebug() << "SkyCultureMaker: Exporting sky culture...";
150-
QJsonObject scJsonObject = currentSkyCulture->toJson();
155+
bool mergeLinesOnExport =
156+
StelApp::getInstance().getSettings()->value("SkyCultureMaker/mergeLinesOnExport", true).toBool();
157+
qDebug() << "SkyCultureMaker: Exporting sky culture. Merge lines on export:" << mergeLinesOnExport;
158+
QJsonObject scJsonObject = currentSkyCulture->toJson(mergeLinesOnExport);
151159
QJsonDocument scJsonDoc(scJsonObject);
152160
if (scJsonDoc.isNull() || scJsonDoc.isEmpty())
153161
{

plugins/SkyCultureMaker/src/gui/scmSkyCultureExportDialog.ui

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,13 @@
121121
</property>
122122
</widget>
123123
</item>
124+
<item>
125+
<widget class="QCheckBox" name="mergeLinesCB">
126+
<property name="text">
127+
<string>Merge constellation lines into polylines on export</string>
128+
</property>
129+
</widget>
130+
</item>
124131
</layout>
125132
</widget>
126133
</item>

0 commit comments

Comments
 (0)