Trennung von internen IDs und Anzeigenamen für Punkte und Objekte

Hallo zusammen, :slight_smile:

ich möchte eine Idee zur Datenarchitektur und Formelverwaltung in Seamly2D zur Diskussion stellen: die vollständige Entkopplung von internen Objekt-IDs und frei wählbaren Anzeigenamen (Labels).

Die Ausgangslage

Aktuell fungiert der sichtbare Punktname gleichzeitig als interne ID im Datenmodell und in den Formeln. Wenn ein Punkt umbenannt wird, muss das System alle Formeln im Hintergrund parsen und anpassen, was bei komplexen Schnitten fehleranfällig ist und die Flexibilität im Workflow einschränkt.

Das Konzept

Backend / XML: Jedes Objekt (Punkt, Linie etc.) erhält eine unveränderliche, interne ID (z. B. ein inkrementeller Zähler oder UUID wie id=“pt_042”).

Frontend / UI: Der Nutzer sieht und editiert ausschließlich lesbare Namen (label=“A1” oder label=“Brustpunkt”).

Formel-Engine: Formeln speichern im XML intern ausschließlich die Referenzen auf IDs. Der Formeleditor rendert beim Öffnen on-the-fly die lesbaren Namen und übersetzt eingegebene Namen beim Speichern wieder zurück in die IDs.

Vorteile dieses Ansatzes

Sofortige und risikofreie Umbenennung (O(1)):

Wenn ein Punkt umbenannt wird, ändert sich im XML genau ein einziges Attribut (das Label des Punktes). Keine einzige Formel im gesamten Schnitt muss neu geschrieben werden.

Maximale Datenintegrität im Abhängigkeitsgraphen (DAG):

Die mathematische Struktur des Schnitts bleibt absolut stabil, unabhängig davon, wie oft Bezeichnungen für die Dokumentation oder Lesbarkeit angepasst werden.

Saubere Diffs in der Versionskontrolle:

Bei der Nutzung von Git oder Datei-Vergleichen führt eine reine Namensanpassung nicht mehr zu Dutzenden geänderten Formelzeilen, sondern bleibt auf ein einziges XML-Element beschränkt.

Flexibilität für Workflows und Schnittsysteme:

Nutzer können Punkte nach Belieben anpassen (z. B. von Standard-Kürzeln wie A1 zu aussagekräftigen Namen wie Halsloch_hinten), ohne Angst haben zu müssen, komplexe Konstruktionen zu beschädigen.

Zukunftssicherheit:

Die Basis für spätere Features wie modulare Schnittblöcke, Schnitteil-Bibliotheken, und ganz wichtig- dem dependency tree- oder mehrsprachige Schnittvorlagen wird geschaffen, da Namen modular austauschbar sind.

Wie seht ihr diesen Ansatz aus architektonischer Sicht und im Hinblick auf die User Experience? Ich freue mich auf euer Feedback und eure Gedanken dazu!

You have to think 'inside" the box. Changing the structure now will break every existing pattern.

Do that and you will have a LOT of p*ssed off users.

You can already do that. By correctly naming points from the start. BTW… you start namng points with names like ‘back_neckhole’ you will soon have a mess when you start creating curves and then rotating and mirroring them. Or worse when a pattern is exported as a set of instructions.

And how do you propose to do that? Lets say you have pt_042 and pt_056 and they both have the name ‘this_point’

How do you translate ‘this_point’ back to an id? Is it pt_042 or pt_056?

I love the idea, but this is not a plan. Apparently you hope to achieve X by achieving X. So, how do you plan to tie the point names to the point IDs in a way which is more flexible than the current system? It almost seems like you’re trying to describe the current XML use, but concluding that it will work differently than it does.

Even as is, if I make two lines between point A1 & point A1_A1 (because people do silly things, maybe I set my line color to a shade that I couldn’t tell apart from my background, & forgot about it) & then try to call on AngleLine_A1_A1_A1, which one is chosen? (This is just one of the reasons why I make a habit of ensuring that my point names lack underscores.) If Seamly were to auto-update all formulae, if I were to change A1 to Halslock_hinten what’s to prevent my reference in a formula to A10 from getting changed to Halslock_hinten0?

But I’ve spent way too much time trying to figure out how to make this brilliant idea actually work without completely re-programming Seamly, so I’d better leave it here.

:unicorn:

Exactly… changing the data architecture means totally rewriting the applications. Thus my we have to think ‘inside the box’. Plus changing the data architecture breaks existing patterns… good luck writing a conversion routine.

And thus one of the stumbling blocks to fixing formulas in a ‘smart’ way. Globally searching and replacing is always fraught with the potential to introduce errors. It’s why when I do it with the code base I always look at search results t see what exactly is going to get changed before deciding yes replace all.

Danke für das Feedback @Douglas und @Pneumarian.

​Ich glaube, hier liegen ein paar grundlegende Missverständnisse darüber vor, wie eine token- und ID-basierte Datenarchitektur im Vergleich zu naivem Text-Suchen-und-Ersetzen funktioniert. Lasst mich die drei Kernpunkte kurz aufklären:

​1. Eindeutige Namen bleiben weiterhin Pflicht (Zur Frage nach doppelten Namen)

Die Trennung von interner ID und Anzeigename bedeutet nicht, dass Namen beliebig doppelt vorkommen dürfen. Das UI erzwingt weiterhin ein striktes Eindeutigkeits-Constraint.

​Wenn pt_042 den Namen this_point hat, verbietet das System schlichtweg, dass pt_056 denselben Namen bekommt.

​Der Unterschied: Der Name ist jetzt frei editierbar, während die interne Referenz (pt_042) unveränderlich bleibt.

​2. Das A1 \to A10 Problem wird hierdurch gelöst, nicht verursacht

Pneumarian merkte an: „Was verhindert, dass beim Umbenennen von A1 in Halsloch_hinten eine Referenz auf A10 zu Halsloch_hinten0 wird?“

​Genau dieser Fehler passiert bei herkömmlichem String-Replacement. In einem ID-basierten System ist dieser Bug technisch ausgeschlossen:

​In der Datei steht in der Formel intern nicht der Text A1, sondern ein fester Token/ID: Line(pt_1, pt_10).

​Wird pt_1 von A1 in Halsloch_hinten umbenannt, ändert sich im gesamten XML nur ein einziges Attribut am Punkt selbst (label=“Halsloch_hinten”).

​Keine einzige Formel wird angefasst oder im Text umgeschrieben.

​Beim Anzeigen im UI schaut der Formel-Parser in die Symboltabelle: pt_1 wird als Halsloch_hinten dargestellt, pt_10 bleibt A10. Eine Verwechslung ist unmöglich.

​3. Abwärtskompatibilität & Dateikonvertierung (Alte Schnittmuster brechen nicht)

Eine Konvertierungsroutine für bestehende Dateien ist deterministisch und sauber umsetzbar:

​Beim Öffnen einer alten Datei liest ein Konverter das bestehende Schema ein.

​Die bisherigen Punktnamen werden 1:1 als Frontend-Labels übernommen (label=“A1”).

​Das System generiert im Hintergrund einmalig die internen IDs z.B. (id=“pt_1”) und ersetzt die Namen in den Formeln durch die entsprechenden ID-Tokens.

​Für den Nutzer ändert sich optisch und funktional absolut gar nichts – seine bisherigen Schnitte sehen exakt gleich aus, basieren im Hintergrund aber auf einem stabilen Fundament.

​Dass ein solches Refactoring in der bestehenden C++/Qt-Codebasis Entwicklungsaufwand bedeutet, steht außer Frage. Rein architektonisch ist die Trennung von Identifier und Label jedoch der Standard in modernen parametrischen CAD-Systemen (wie FreeCAD oder Onshape), genau um Formelkorruption und instabile Abhängigkeitsbäume dauerhaft zu verhindern.

Well, we are now well past my understanding of how Seamly uses the XML as is. It sounds like all of my doubts would probably have resulted in a broken pattern already, & thus be irrelevant.

I’m still concerned that it would introduce bloat, rather than cleaning up the code, but if you can produce a lean working implementation, I’m sure the Dev team would be delighted to merge it. At the moment, getting a workable Marker mode functioning is a higher priority toward getting Seamly working in accordance with industry standards, so @Douglas is prioritising that, & functionality issues, over overhauling the backend.

This concept is related to at least these two standing issues:

:unicorn:

ich habe schonmal einen kleinen Zwischenbefund: ID-Infrastruktur für formelstabile Referenzen ist bereits vorhanden, wird aber nicht genutzt

VGObject, die Basisklasse aller geometrischen Objekte (Punkte, Linien, Kurven), besitzt bereits zwei getrennte Felder:

  • quint32 id() / setId() — eine unveränderliche, numerische ID, verwaltet als Schlüssel in VContainer::gObjects (QHash<quint32, QSharedPointer<VGObject>>, vcontainer.h:142)
  • QString name() / setName() — der sichtbare, editierbare Anzeigename

Diese Trennung existiert also technisch bereits im Objektmodell. Das Problem liegt ausschließlich in der Formel-Engine: VContainer::variables (QHash<QString, QSharedPointer<VInternalVariable>>, vcontainer.h:147) — die von qmu::QmuParser beim Formel-Parsing abgefragte Struktur — ist zwingend über QString name als Schlüssel indiziert, nicht über die vorhandene id. Formeln referenzieren also ausschließlich den Namen als String. Warum man sich damals dafür entschieden hat verstehe ich nicht so ganz. Naja…

Konsequenz: Beim Umbenennen (VAbstractPoint::SetPointName, vabstractpoint.cpp:99-105) wird lediglich obj->setName() gesetzt und ein Full-Reparse (NeedFullParsing) getriggert — es existiert keine Rename-Propagierung, die Formeltext durchsucht und anpasst. Referenzierende Formeln brechen dadurch gelegentlich mit “Variable nicht gefunden”.

Auch im XML (.sm2d) ist das id-Attribut (AttrId, vdomdocument.cpp:149) bereits pro Objekt vorhanden, wird aber nur als Laufzeit-Zähler behandelt, nicht als stabiler Formel-Anker.

Für die geplante Umstellung heißt das: Der Umbau ist kein Neubau der ID-Struktur, sondern eine Umverdrahtung — VContainer::variables muss auf id als Schlüssel umgestellt werden, und die Formel-Speicherung muss beim Sichern/Laden zwischen ID (intern) und Name (Anzeige) übersetzen. Ich setz mich mal ran.

Yes. IMO it’s not worth the time and effort to change somethng users are not clamoring for. Since 2018 with nearly 150 suggestions there has been no real request to nake it easier to rename points. Which BTW is the only tool you can rename as lines and curves are named based on the point names.

The only thing iI can recall is a discussion during a team meetiing when we were talking about fixing the “broken formula” dialog, where there needs to be a way to intelligently automate the process of renaming broken formulas. There is an issue on Github for this. The is issue not renamng the point - we an already do that, but rather fixing all the references in formulas.

We don’t need to overhaul the naming archiecture… we just need to able to automate parsing the pattern and fixing broken references.

Right. That’s aleady known. Except a "lne"tool is not a VGObject. That is you can only select points and curvesi on a scene. The VObjects are only the graphical reprsentation of a tool.

The id is the same “immutable” id’s used in the VObjects. Any time a new tool, image, modeling node, pattern piece,etc is added… it’s assigmed the next unique id number. Could QUuiid’s have been used? Sute… but 16byte numbers for every id in the xml would be overkill.

Danke @Douglas für deine offene Einschätzung.

Aus Software-Architektur-Sicht sehe ich den Ansatz, Formeln nachträglich über automatisierte Skripte zu „flicken“, allerdings kritisch. Das kuriert lediglich ein Symptom, anstatt die eigentliche Ursache zu beheben.

String-basiertes Referenzieren in einer parametrischen CAD-Engine bringt unvermeidbare Folgeprobleme mit sich:

  • Endlose Randfälle: Jedes Skript, das Formeln per String-Parsing repariert, muss komplexe Ausdrücke, verschachtelte Funktionen und Sonderzeichen berücksichtigen. Das erzeugt fragile Heuristiken und langfristige Technical Debt.

  • Blockade künftiger Kern-Features: Solange Identität und Anzeige nicht entkoppelt sind, bleiben essenzielle CAD-Funktionen wie modulare Schnittblöcke, fehlerfreies Copy & Paste zwischen Schnitteilen oder lokalisierbare/mehrsprachige Schnittmuster extrem schwer und unsauber umsetzbar.

  • Undo/Redo & DAG-Integrität: Ein sauberer, performanter Dependency-Graph basiert mathematisch auf unveränderlichen IDs und Kanten – nicht auf dynamischen Text-Bezeichnern.

Da die unveränderliche id im Backend (VGObject, AttrId) ohnehin schon existiert, ist das Fundament eigentlich bereits gelegt. Es einmal sauber an den Formel-Parser anzubinden, ist zwar ein Refactoring-Schritt, bringt Seamly2D aber auf einen echten Industriestandard und erspart der Codebasis jahrelange Workarounds um ein bekanntes Anti-Pattern.

Ich werde mir das im Code in einem separaten Branch als Proof of Concept anschauen. Am Ende zeigt oft erst eine funktionierende Implementierung, wie schlank eine solche Lösung in der Praxis sein kann. Dass oft andere Themen Vorrang bekommen ist verständlich. Deshalb versuche ich mich einfach dran, sodass ihr euch auf anderes Konzentrieren könnt. Updates folgen

I look forward to seeing what you bring out!

:unicorn:

BTW… using FreeCad for your example as an 'industry standard" was probably not the best choice. FreeCad has a history with naming issues. In fact it has it’s own name… Topological Naming Problem (TNP). :roll_eyes:

Uff- gut zu wissen. Na dann machen wirs eben besser :wink:

Done :slight_smile:

ich hab nen PR erstellt. Die erste Folge ist, dass man ab sofort alles umbenennen kann und sich alles automatisch korrigieren sollte: jede Formel, jede Bezeichnung. Gerne mal testen!