Make all objects accessible, not just the ones prior in the sequence?

How else would you parse the file?

The val xml is representative of the history ( or vice versa). It starts with draft block 1… creates the 1st point - lets assume basepoint A, creates the next tool…A1, etc etc. It’s like trees… were leaves don’t just grow in the middle of the air. We can’t just arbitrarily start creating a pattern in the middle somewhere… and again, it’s the formulas. A formula will usually reference another tool, and that tool’s class HAS TO exist. And conversely you can’t know about future tools, unless you parse 1st - so any formulas are adjusted, then you can parse again with the now known future tools. Take away the formulas and we don’t have this issue, but then we wouldn’t have a parametric pattern app either - we would just have your typical vector drawing app.

1 Like

The xml IS read into memory when you load a pattern. It’s read into a QDomDocument. The QDomDocument is a class to handle reading and writing xml fikes. When you save a DomDoc it is written back to the (an) xml. A DomDoc does not have to be written linear… that’s not why val files are linear. In fact everytime you make a change to a tool - like changing it’s line color - you’re editing the DomDoc non linear.

The issue is not whether it’s in memory or not, it’s a matter of being able to (pre) parse the document. You have to be able to parse the whole document so you can (math) parse all the formulas… then you can go through again and create the tools to display on the screen. Currently we don’t always have to do a full parse… such as moving a point name. If we wanted to make all tools available to any other tool, we’d have to full parse with every change that affects formulas.

Exactly. It’s the parametric nature of the apps that make it what it is… otherwise like I said you’ve just got another vector app like Inkscape, Illustrator, or Coreldraw. It’s the formulas though that are imposing the linear nature of the app.

2 Likes

@Douglas and @Grace, I think I did not express myself sufficiently clear yesterday. The reason why I compare Seamly2D to spreadsheets is that both programs share a fundamental similarity, which is largely absent in graphical programs like inkscape etc. The similarity, at an abstract level, is the following. Both programs have objects (cells in a spreadsheet, points, lines etc. in Seamly) that depend on user input and/or features of other objects in the program. An object is a formal procedure, resulting in a tangible product (a number in a spreadsheet, a line or curve etc in Seamly), as a function of its input. Because the input can consist of other objects, this creates a tree of dependencies among the objects. In such a tree, an object can only be calculated and produced under the condition that all objects on which it depends are already known. The dependencies therefore create the problem of calculation order. You cannot calculate all cells in a spreadsheet in a random order, and neither can you do this with objects in Seamly. The way in which Seamly treats this calculation order problem, is by imposing chronological order. An object can only depend on the objects that were created prior to it. You can cheat a bit by playing with ‘History’, but that does not change the fundamental linear, chronological construction of the program. Spreadsheets could do that too. If the person creating the spreadsheet with all kinds of complex functions, were very orderly, she would introduce all cells in a strict order of dependency and everything would be calculated in chronological order and be fine. But then that person hands this spreadsheet to her boss, and the boss must show that she is on top of things by requiring some changes (I am speaking for myself here, as this is how I tend to treat my students :slight_smile: ). We are entirely costumed to the fact that this is not a fundamental problem. We do not need to redo the entire spreadsheet, just add this additional parameter, change some formulae and check that the result now changes a loss in a profit. How come this is possible? This is because spreadsheets do not calculate cells in the order in which they were typed in, but based on dependencies. A nice forum post describing how this is done in LibreOffice Calc (older versions, I think it is more complicated now) is here: https://forum.openoffice.org/en/forum/viewtopic.php?t=103276. It describes the systems of ranks (called tiers here) that I intuitively suggested yesterday - I only discovered the forum today. You basically asign a tier to every cell, depending on the tiers of the cells it depends on. A cell always has a tier that is one unit higher than the highest tier of the objects it depends on. When recalculating, you first calculate the cells of the lowest tier, then the next one etc. - in this order you are sure that all information is available for the cell X you are calculating. The only thing you have to avoid is circularity, as this is incompatible with the tier system. Modern spreadsheets make it more complex to permit some temporary circularity, but I have no clear insight in how it works precisely and for this discussion it does not matter. Basically, therefore, spreadsheets allow editing of cells because they maintain a dependency tree that allows them to always update the position of a cell in the tier system after a change, and then are assured that every cell can always be calculated, while in the revision you can use almost all other cells (circularity excluded). If you would apply this to Seamly2D, changing an object X would involve the following steps (assuming that a dependency tree already exists, but I think this must be the case):

  1. Check all dependencies of the object X and identify all its descendants, i.e. all objects that depend directly or indirectly on X.
  2. Exclude all these descendants from the formula interface, comparable to how this interface is now restricted to objects that are prior in the chronological sequence. This way, circularity in formulae is avoided.
  3. Check if the points on which X depends are also not circular, i.e. not occurring in the dependency tree as descendants of X
  4. After accepting the modification of X, adjust the dependency tree to reflect the changes in object X. This may consist of cutting some links and adding some new ones
  5. Update the tier level of X. If after the change it depends on an object higher in tier than before the modification, its tier will have to go up.
  6. If the tier has gone up, check all descendants and update their tier also, where needed.

As you can see, this involves only relatively easy and fast database operations, but no repetitive constructions of graphical elements etc. I estimate it should not jeopardize the speed of the program too much. When saving the pattern, the tier information can easily be stored with all the objects, ensuring that the order of drawing the objects is conserved and the pattern appears fast after opening. Also, the stored tiers should be helpful in reconstructing the dependency tree, as this tree could be built up gradually while the objects are already being constructed. The stored calculation order would basically replace the chronological order, which should leave most of the program more or less like it is now.

But please do not misinterpret my suggestion. I am fully aware that this would involve some fundamental changes and is not the easiest operation to implement. Also, it is not urgent as the program now also works fine within some limitations. I only intended this as sketching a longer-term possibility worth looking at.

2 Likes

Yeah —it’s called the History list.

Hence why @Douglas believes it would involve basically a complete re-write of Seamly2D. It has been investigated before.

I hold out hope that once the insidious bugs & messy code get cleaned up an elegant & lite solution will become obvious. I remember that one of the times this issue came up a better method than previously considered did come to light, but that merely brought it down from “Google AI could do it,” to a PC compatible solution.

We are grateful for the input, & if you happen to know of a source of grant money which would be eager to enable someone to take on re-coding Seamly as their day-job, we beg you to please help make the connection! :smiling_face:

:unicorn:

3 Likes

Well after that long dissertation it’s obvious you have it all figured out… who knew Seamly2D is just a spreadsheet?

Good luck in rewriting your own fork to accomplish this. :wink:

3 Likes

Thank you for your suggestion, @peterh. After reading it through, I now have a much clearer idea of what @Douglas was suggesting here (albeit for different purposes):

So, yes. at the moment, @Douglas is busy ‘cleaning’ up the program and adding some very much needed features.

Thank you very much.

1 Like

@Douglas, sorry for being carried away in my attempt to explain what I really meant. I had insufficiently realized that you must not be waiting for such wild and abstract ideas in a situation that is already quite stressed. Thanks @Pneumarian and @Grace for pointing this out. I regret having put this extra burden, especially since in this short time on the forum I have come to know you as an extremely dedicated developer. With this I hope we can close this topic and return to what really matters at this moment?

3 Likes

Sorry for my terse response, but as you might imagine it gets a bit tedious trying to explain to new users why it’s simply not possible (as structured) to allow for NLE of patterns.

Maybe this is the best response to the issue years ago by KMF…

"I would suggest that you pick a patternmaking system and learn it and make at least a few paper patterns. Once you have done this it should be more clear to you why it makes sense to use Valentina the way it is.

I understand your issue with a “forward reference” to a value to be defined in the future, but I believe that to have that issue means you are thinking like a programmer and that thinking like a patternmaker is different. Just my 2 cents".

As a trained draftsmen and pattern maker for 40+ years, I would tend to agree with these statements. Sometimes we just have to accept, and think “inside the box”.

3 Likes

Which, as a scientist for 40+ years, is not exactly what I have been trained in. Anyway, I happily return to my pleated trousers pattern.

1 Like

Since I really have nothing to do at work today, I have the time to read / reread topics on the issue. I found this one by RT - the orginal dev:

“To avoid such a problem we could propose a “forward declaration” agreement. In your case, to get correct position you need recalculate pattern twice. First time you gather information and ignore missed parents data, next time you have all you need to correctly position pieces.”

Which is basically what I’ve said would need to be done. We’d have to parse the pattern twice… kinda of like compiling a program with forward declarations. - you won’t know what the reference value is until the future file is compiled. Again, my concern would be the efficiency hit the app would take having to parse twice.

And Susan’s response on the issue - along the same lines as KMF:

“Learning to make patterns is like learning to create mathematical proofs – you know where you need to go before you begin. Similar to proofs, when you make a mistake you must sometimes start over, but this will happen less and less as you build patternmaking skills, just like building math skills, and very much like learning how to apply engineering knowledge to create a CAD drawing - knowing the engineering is half the problem, understanding how the CAD program works is the other half. To sum up, all the information contained in a pattern is related, and order is important, so there will always be a temporal constraint.”

3 Likes

You are absolutely right in that. Forward projection is a can of worms. It would very easily lead to circularity too. That’s why I think the solution is in making the calculation order different from the chronological order, in such a way that you never have to do a forward projection but still can use ‘later’ objects as long as they are independent. It requires an efficient dependency tree, among other things, but it should never lead to the kind of problems you sketch.

1 Like

My solution is to work on other features that will be far more useful to pattern making, rather than trying to eliminate a minor limitation of the apps, that can easily be overcome by planning a pattern out before hand. :slight_smile:

4 Likes

Fair enough - I guess there is enough to do!

2 Likes

In the mean time, my-pattern.cloud is dependencies aware and if you have any refactoring of a pattern to do you could try it there. There is one caveat, Seamly2D sometimes requires a line to be defined in order to know its length, MyPattern can use the distance between any two points. I’ve not worked out what the logic is that drives the line to be required sometimes, and I don’t want to get into the code for IPR reasons.

I’m guessing, from the error messages you get when loading a corrupt file, that Seamly2D doesn’t parse formulas on load, but just evaluates them optimistically when the value is required. To get a full dependencies map you need to parse the formulas. I’m happy to share any coding or techniques should this rise to the top of the Seamly2D wish list.

3 Likes

Can’t login… I just get an error 500 code?

1 Like

Of course Seamly2D parses the formulas when the pattern is loaded… how else would it create and refresh the geometries to draw each tool’s graphicItem?

2 Likes

I was assuming from observing behaviour, and clearly wrongly, that a library was being used to do the equivalent of an ‘eval’ of the formula given a set of variable values to work from. If this isn’t the case, then you already have the code to know, for a given object the objects that it depends upon, and also the usages of any object. I don’t want to step on anyone’s toes, and i’m Java/Javascript rather than C++, so can’t help with the code base, but I could extract from my work the set of rules. On a related note, if I’m wrong about it being eval-like, then surely you could allow Line_A_B to work for any two points that are already defined?

2 Likes

This nice phrase meets exactly my feelings …

Yours truly, the traditional nerd in service

1 Like

Not sure what a “library” has to do with it? Qt treats libraries in 2 ways - static, where the code is complied and linked IN the app binary OR dynamic, where the code is compiled and a dll is created, which is linked at run time. You can do it either way with same code, and in end makes no operational difference. Dll’s are usually used where the author does not wish to release the source code.

That being said… the bulk of the Seamly apps are libraries. Specific to the formulas, RT ported the MuParser math parser to Qt… thus QMuParser. For whatever reason, it’s built as a dll?

Now for a rough flow outline:

Load pattern from XML to a QDomDocument in memory. Parse Increments. Parse Draw Elements (AKA draft blocks). Within each Draw element parse each child tool element in sequential order followed by the detail ( pattern piece) elements.

As each tool is parsed, each formula is 1st translated. Then the formula is evaluated. 1st to see if any variables (increments, measurements, other tool variables) or math tokens exist, if not it’s just a number - no calculation required - return number. If there are tokens then the formula is Eval()'d, where the variables are replaced with their value. Then the formula is math parsed via QMuParser, and the final calc returned.

Since each tool is built sequentially, only the tool variables (line length / angle, etc) that were created BEFORE are available to be Eval()'d. THAT’S why future tool variables are NOT yet available to use in tools created before hand - they’re not in the data container yet.

I should note that as each tool is created, for each other parent tool it references, it calls that tool’s IncrementReferens(parentId), which increments it’s use counter by 1, and if that tool is deleted it calls the DecrementReferens(patentId) of each parent. So if you go to delete a tool where it’s use count > 0, you can’t delete it, until all child tools are deleted.

Editing a tool’s formula in a dialog or the Properties Editor that changes geometry will probably trigger a reparse of the pattern via the same evaluation of the formulas.

That’s it in a nutshell.

The language used was not a big issue for me since I’ve learned dozens of languages over 45+ years (including Java), it was easy to pick up the bulk of the syntax of C++ in a couple weeks. It’s the learning the Qt api that takes a long time… not to mention reading through piles of poorly styled code.

3 Likes

Wo wir, die wir ausschließlich Muster erstellen immer gerne helfen.

1 Like