sketch.Geometry[index].Tag == Unique identification survive changes?

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
paullee
Veteran
Posts: 5135
Joined: Wed May 04, 2016 3:58 pm

sketch.Geometry[index].Tag == Unique identification survive changes?

Post by paullee »

Hi, when i am struggling through some sketch geometry issues, i come across the sketch.Geometry[index].Tag function....wondering...

Testing it with a sketch with 3 edges returns something below... and seem to be something Abdullah mention earlier...?
  1. Further test show this Tag behaves interestingly... It return a UUID kind of string, unlike the Geometry[index] / Shape.Edge[Index]..

    (sorry, i can't read c++ and a beginner in python only, so what I can do is lengthy trial and error below...)

    Code: Select all

    >>> se1=s.Geometry[0]
    >>> se2=s.Geometry[1]
    >>> se3=s.Geometry[2]
    >>> 
    >>> se1.Tag
    'a5ee5ee6-7937-4873-925f-579d1d8be4b8'
    >>> se2.Tag
    '49e613b7-a5dd-474d-a16b-52d15e7cefc3'
    >>> se3.Tag
    '8181cc10-e04b-4384-8115-54219c49078e'
  2. Now delete '2nd' edge... assign and read the Tag again... no '3rd' edge of cos.
    ... now the geometry index 'shift', which is kind of 'topological issues' / problem?, referencing to same index leads to wrong element..
    ... but seem the Tag is 'constant' right?

    Code: Select all

    >>> s01=s.Geometry[0]
    >>> s02=s.Geometry[1]
    >>> s03=s.Geometry[2]
    Traceback (most recent call last):
      File "<input>", line 1, in <module>
    IndexError: list index out of range
    >>> 
    >>> s01.Tag
    'a5ee5ee6-7937-4873-925f-579d1d8be4b8'
    >>> s02.Tag
    '8181cc10-e04b-4384-8115-54219c49078e'
  3. Then, w/o saving it, close it and re-open it (i.e. keep 3 edges)...
    ... so it seem the Tag is generated each time the file is opened, but never change (unlike the geometry or shape.edge index which change) when some edges in the middle are deleted.

    Code: Select all

    >>> se1.Tag
    '622356c1-5d35-401d-8e49-3eb8ec26e973'
    >>> se2.Tag
    '61d5bc7c-055b-417d-a41c-33032ad1499b'
    >>> se3.Tag
    '7833b3c9-2ebf-45c9-96ef-38c576a0e0ee'
Thanks for any hints, this may be very useful to 'identify' a geometry elements which currently to me is problematic!
(Which I am hoping Realthunder's Sketch Export feature would have solved it all along...!) one of missing pieces in the puzzle!

abdullah wrote: Sat Feb 10, 2018 8:47 am
paullee wrote: Sat Feb 10, 2018 8:03 am
I am interesting in the 'unique identifier' you mentioned, hope somebody can help looking in the code and use it. My test to use the convoluting workflow: datum constraints+expression engine+reference datum constraints is not productive though works. I guess the 'unique identifier' would make resolve it fundamentally.

Thanks anyway.
The code is this (src/Mod/Part/App/Geometry.h), see getTag() below and the protected functions:

Code: Select all

class PartExport Geometry: public Base::Persistence
{
    TYPESYSTEM_HEADER();
public:
    virtual ~Geometry();

    virtual TopoDS_Shape toShape() const = 0;
    virtual const Handle(Geom_Geometry)& handle() const = 0;
    // Persistence implementer ---------------------
    virtual unsigned int getMemSize(void) const;
    virtual void Save(Base::Writer &/*writer*/) const;
    virtual void Restore(Base::XMLReader &/*reader*/);
    /// returns a copy of this object having a new randomly generated tag. If you also want to copy the tag, you may use clone() instead.
    /// For creation of geometry with other handles, with or without the same tag, you may use the constructors and the sethandle functions.
    /// The tag of a geometry can be copied to another geometry using the assignTag function.
    virtual Geometry *copy(void) const = 0;
 ...

EDIT: https://forum.freecadweb.org/viewtopic. ... 32#p214271

Screenshot from 2018-05-06 02-46-28.png
Screenshot from 2018-05-06 02-46-28.png (145.07 KiB) Viewed 2865 times
realthunder wrote: Sat Feb 24, 2018 9:11 am
[*]It seem edges are now using 'unique identifier' that would not repeated / recycled right? And it become safe again to use Link to External Edges right?
Yes, it calculates the name of external edge by hashing linked object_name+element_name. You can delete the external edge, and later link back to the same edge, the name stays the same. However, to have a complete safe external link, you still need the linked object to have a stable topological name, and I plane to work on that too.

EDIT: https://forum.freecadweb.org/viewtopic. ... 30#p216875
Attachments
Test_ Sketch Edge Intersection.fcstd
(5.69 KiB) Downloaded 61 times
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: sketch.Geometry[index].Tag == Unique identification survive changes?

Post by realthunder »

Yes, the Tag is not persistent, which is why I added an ID to each Geometry in my branch. You can try it in one of my releases. The ID is unique among its owner sketch. It can be read and written in Python. Be careful when you change the ID though, it affects your modeling. It lets you do advanced stuff, like replace a straight line with an Arc. See the swap ID example here. It is implemented using Python by simply swap the ID of two selected geometries.
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
paullee
Veteran
Posts: 5135
Joined: Wed May 04, 2016 3:58 pm

Re: sketch.Geometry[index].Tag == Unique identification survive changes?

Post by paullee »

realthunder wrote: Sat May 05, 2018 10:47 pm Yes, the Tag is not persistent, which is why I added an ID to each Geometry in my branch. You can try it in one of my releases. The ID is unique among its owner sketch. It can be read and written in Python. Be careful when you change the ID though, it affects your modeling. It lets you do advanced stuff, like replace a straight line with an Arc. See the swap ID example here. It is implemented using Python by simply swap the ID of two selected geometries.
I always hope your works would be merged in master branch very soon to use the features indeed :) which solve a numbers of problems!
(The discussion there is far far too advanced for me :oops: , would like to try compiling (just only once before for a bug fix earlier) when I have a moment and courage to do so! )

By 'persistent' here I just mean a particular problem out of the several you are resolving (no need that far for the problem with me at the moment) - just to identify sketch edge other than using 'index' which is the serial order and it re-order when some edges are deleted.
I always think there should have been something there I conceived in the post.
https://forum.freecadweb.org/viewtopic.php?f=8&t=23867 Topological Naming - Sketcher Constraints Survive Change? Test

So, even though deleting an edge therein would change all the index of the element, 'Link to external Edge' would fail.... but constraints within sketcher itself would not break, it still adhere to that particular edge without problem.

Abdullah indicated something in c++, which I have no knowledge at all - when i revisit it, it contain something about 'Tag'...
https://forum.freecadweb.org/viewtopic. ... 32#p214280Sketcher: Virtual Space

Code: Select all

    /// returns the tag of the geometry object
    boost::uuids::uuid getTag() const;
protected:
    /// create a new tag for the geometry object
    void createNewTag();
    /// copies the tag from the geometry passed as a parameter to this object
    void assignTag(const Part::Geometry *);
So when I just drop into the Tag in python, noted above code, just hope it is the 'current' 'unique identifier' for sketch element that could readily usable ...
... It seems kind of 'semi'-persistent? --- 'Persistent' throughout a session after the model is loaded??? ...Maybe it is not how sketcher identify the elements? So how sketch identify the 'element' e.g. for constraints?
abdullah
Veteran
Posts: 4935
Joined: Sun May 04, 2014 3:16 pm
Contact:

Re: sketch.Geometry[index].Tag == Unique identification survive changes?

Post by abdullah »

paullee wrote: Sat May 05, 2018 7:00 pm when i am struggling through some sketch geometry issues, i come across the sketch.Geometry[index].Tag function....wondering...
It is exactly what you wrote ;) . On creation (that can be when you actually insert a new geometry, or when you retrieve one from a saved file), a UUID is generated. This UUID lives on this object until it is destroyed. Closing the document effectively destroys the object.

It is not "persistant" (when you load a saved file you get another UUID), because it is not serialized ATM. For the use it was originally intended there is no need for serialization. However, if a new use case would appear, it could be serialized.

There are more c++ functions for mangling UUIDs, as sometimes it is necessary to make a copy and change the UUID (for example the copy function of the sketcher, that generates a second object equal to the first object, but it is actually a new object with its own UUID). Generally speaking (valid for geometry and constraints), you can "copy" or "clone" an object. A copy is an equal object with a new UUID, a clone is an equal object with the same UUID. In the case of the constraints the expression manager can keep changes on a constraint because (as far as) the UUID is unchanged.
paullee wrote: Sun May 06, 2018 2:59 am Abdullah indicated something in c++, which I have no knowledge at all
Well, you can't read C++ and I can't read Python. It sounds fair to me :lol:
paullee
Veteran
Posts: 5135
Joined: Wed May 04, 2016 3:58 pm

Re: sketch.Geometry[index].Tag == Unique identification survive changes?

Post by paullee »

abdullah wrote: Sun May 06, 2018 6:23 am
It is exactly what you wrote ;) . On creation (that can be when you actually insert a new geometry, or when you retrieve one from a saved file), a UUID is generated. This UUID lives on this object until it is destroyed. Closing the document effectively destroys the object.

It is not "persistant" (when you load a saved file you get another UUID), because it is not serialized ATM. For the use it was originally intended there is no need for serialization. However, if a new use case would appear, it could be serialized.

There are more c++ functions for mangling UUIDs, as sometimes it is necessary to make a copy and change the UUID (for example the copy function of the sketcher, that generates a second object equal to the first object, but it is actually a new object with its own UUID). Generally speaking (valid for geometry and constraints), you can "copy" or "clone" an object. A copy is an equal object with a new UUID, a clone is an equal object with the same UUID. In the case of the constraints the expression manager can keep changes on a constraint because (as far as) the UUID is unchanged.
Thanks! It is good piece of information!
  1. Just wonder how Constraints information is saved in file if UUID is not used? Use the 'last version' of geometry index upon saving? Then rebuild the index : UUID upon every re-opening....? So why not just use the UUID? (sorry if the question does not make sense for programmer)
  2. Current 'Link to External Geometry' to shape including Sketcher Edge would break if there is certain change.... if sketcher constraints recognise each edge to keep constraint 'persistent', I always wonder why an 'external link' to a sketch geometry should failed if UUID is used, which is present...

    I.E. 'link to external geometry' of a sketch element SHOULD NOT BREAK! It help the implementation of the 'skeleton' sketch / resilient modelling strategy indeed!

    (another 'problem' that 'internal index of a sketch does not match internal index" should be overcome easily - "Sketch - Identify Geometry Index (inside and outside Edit Mode) - https://forum.freecadweb.org/viewtopic. ... 22&t=27215
I am think if Tag is 'semi-persistent', I wonder if sketch use the 'method' mentioned above to check which edge are which edge and I can 'simulate' something sketch do 'internal' ...?
  1. onChange() or Excute()...etc? - For particular geometry elements that user want to 'identify' (e.g. need to 'sketch export') a method in SketchPythonObject (which I am learning to use) may make/update a 'custom dictionary'' of UUID : 'geometry index' used at that moment (overloading FC....?)
  2. then when the file is saved, the most uipdated 'custom dictionary' is saved.
  3. onDocumentRestore() - the Geometry Index : UUID are updated where 'new generation' of UUID replaced the 'previous version' (before any change could have done)
... I hope this make sense...?
abdullah wrote: Sun May 06, 2018 6:23 am
paullee wrote: Sun May 06, 2018 2:59 am Abdullah indicated something in c++, which I have no knowledge at all
Well, you can't read C++ and I can't read Python. It sounds fair to me :lol:
Well, i just start learning elementary python at 'leisure' time... just newbie indeed... and not a programmer of any kind at all :oops:


Thanks anyway!
abdullah
Veteran
Posts: 4935
Joined: Sun May 04, 2014 3:16 pm
Contact:

Re: sketch.Geometry[index].Tag == Unique identification survive changes?

Post by abdullah »

paullee wrote: Sun May 06, 2018 10:45 am Just wonder how Constraints information is saved in file if UUID is not used? Use the 'last version' of geometry index upon saving? Then rebuild the index : UUID upon every re-opening....? So why not just use the UUID? (sorry if the question does not make sense for programmer)

Code: Select all

Basically yes. This is what is stored:

void Constraint::Save (Writer &writer) const
{
    std::string encodeName = encodeAttribute(Name);
    writer.Stream() << writer.ind()     << "<Constrain "
    << "Name=\""                        <<  encodeName              << "\" "
    << "Type=\""                        <<  (int)Type               << "\" ";
    if(this->Type==InternalAlignment)
        writer.Stream() 
        << "InternalAlignmentType=\""   <<  (int)AlignmentType      << "\" "
        << "InternalAlignmentIndex=\""  <<  InternalAlignmentIndex  << "\" ";
    writer.Stream()     
    << "Value=\""                       <<  Value                   << "\" "
    << "First=\""                       <<  First                   << "\" "
    << "FirstPos=\""                    <<  (int)  FirstPos         << "\" "
    << "Second=\""                      <<  Second                  << "\" "
    << "SecondPos=\""                   <<  (int) SecondPos         << "\" "
    << "Third=\""                       <<  Third                   << "\" "
    << "ThirdPos=\""                    <<  (int) ThirdPos          << "\" "
    << "LabelDistance=\""               <<  LabelDistance           << "\" "
    << "LabelPosition=\""               <<  LabelPosition           << "\" "
    << "IsDriving=\""                   <<  (int)isDriving          << "\" "
    << "IsInVirtualSpace=\""            <<  (int)isInVirtualSpace          << "\" />"
    
    << std::endl;
}
I think you are familiar with "First" "FirstPos" "Second" "SecondPos"... which are the geoIds and Pos intervening in the constraint. If the list of geoids changes (deleting), the geoids of the constraints are "recalculated" and changed. So what is stored is basically the geoids. As far as the geoids and constraints are "in sync" at the moment of saving, they will be "in sync" at the moment of loading. As you indicate the UUID will be different after loading, because

To the last question: Why not using UUID and storing it?
A. Historical reasons? There was no UUID in FreeCAD 0.15 for constraints AFAIR. There was no UUID for geometry before v0.17.
B. Not needed for a single sketch? Models do not break while being saved and reloaded.
paullee wrote: Sun May 06, 2018 10:45 am Current 'Link to External Geometry' to shape including Sketcher Edge would break if there is certain change.... if sketcher constraints recognise each edge to keep constraint 'persistent', I always wonder why an 'external link' to a sketch geometry should failed if UUID is used, which is present...

I.E. 'link to external geometry' of a sketch element SHOULD NOT BREAK! It help the implementation of the 'skeleton' sketch / resilient modelling strategy indeed!
Probably I am wrong, because I thought that sketches did not break because imported external geometry from another sketch, unless you delete the imported edge in the original sketch. I am going to do some tests...

... yep you are right, I am wrong, because an external link is actually (DocumentObject (e.g. sketch) + string), if you delete any element coming before the linked one in the original sketch, then the external link is either broken (if the linked was the last geometry) or it is moved to whatever was the geometry coming after the linked one. This is because the "string" part of the link (in the second sketch) is not updated on deletion (of an element in the original sketch).

There are several ways of "fixing this". One is certainly having a global identifier for all the geometries, can be a UUID or a unique index assigned on creation of the geometry object, which is stored. Then this index can be used in the "string" part of the link.

Another way is, when a geometry element of a sketch is deleted, iterate all the external links in the Document and if the obj is the current sketch, and the string is an index after the one being deleted, then update it (decrease the edge number by one). If the index is exactly the one being deleted, it could even warn the user that he is breaking the link.

paullee wrote: Sun May 06, 2018 10:45 am (another 'problem' that 'internal index of a sketch does not match internal index" should be overcome easily - "Sketch - Identify Geometry Index (inside and outside Edit Mode) - https://forum.freecadweb.org/viewtopic. ... 22&t=27215


I am think if Tag is 'semi-persistent', I wonder if sketch use the 'method' mentioned above to check which edge are which edge and I can 'simulate' something sketch do 'internal' ...?
  1. onChange() or Excute()...etc? - For particular geometry elements that user want to 'identify' (e.g. need to 'sketch export') a method in SketchPythonObject (which I am learning to use) may make/update a 'custom dictionary'' of UUID : 'geometry index' used at that moment (overloading FC....?)
  2. then when the file is saved, the most uipdated 'custom dictionary' is saved.
  3. onDocumentRestore() - the Geometry Index : UUID are updated where 'new generation' of UUID replaced the 'previous version' (before any change could have done)
... I hope this make sense...?
I know the indices are different inside and outside the sketch, but I never saw that as a problem. Of course, if it helps you there, you may use the Tag.

What you say, which should work, is an overcomplicated solution, because you are using python at user level to overcome a limitation at c++ level. Needless to say that the best is to fix the c++ level. But, isn't all this something realthunder has already solved?
paullee
Veteran
Posts: 5135
Joined: Wed May 04, 2016 3:58 pm

Re: sketch.Geometry[index].Tag == Unique identification survive changes?

Post by paullee »

abdullah wrote: Sun May 06, 2018 3:18 pm
paullee wrote: Sun May 06, 2018 10:45 am I.E. 'link to external geometry' of a sketch element SHOULD NOT BREAK! It help the implementation of the 'skeleton' sketch / resilient modelling strategy indeed!
... yep you are right, I am wrong, because an external link is actually (DocumentObject (e.g. sketch) + string), if you delete any element coming before the linked one in the original sketch, then the external link is either broken (if the linked was the last geometry) or it is moved to whatever was the geometry coming after the linked one. This is because the "string" part of the link (in the second sketch) is not updated on deletion (of an element in the original sketch).

There are several ways of "fixing this". One is certainly having a global identifier for all the geometries, can be a UUID or a unique index assigned on creation of the geometry object, which is stored. Then this index can be used in the "string" part of the link.
...

What you say, which should work, is an overcomplicated solution, because you are using python at user level to overcome a limitation at c++ level. Needless to say that the best is to fix the c++ level. But, isn't all this something realthunder has already solved?

Thanks again for all this information and test!

Glad you see this problem... I had hope some developer here find this is a 'bug' and fix it :) (I do not remember if i have posted a bug report...?)

Realthunder should have solved this along with other critical improvement, to my understanding but not understanding the technicality in the discussion which is far from my knowledge level. I think those improvement are yet to be incorporated into the master branch...need to wait? Because I trying to use Sketch / SketchPythonObject for Arch object, I drop into this 'shortcoming' and want this could change soon... thanks anyway.
abdullah
Veteran
Posts: 4935
Joined: Sun May 04, 2014 3:16 pm
Contact:

Re: sketch.Geometry[index].Tag == Unique identification survive changes?

Post by abdullah »

paullee wrote: Sun May 06, 2018 5:38 pm
Thanks again for all this information and test!

Glad you see this problem... I had hope some developer here find this is a 'bug' and fix it :) (I do not remember if i have posted a bug report...?)

Realthunder should have solved this along with other critical improvement, to my understanding but not understanding the technicality in the discussion which is far from my knowledge level. I think those improvement are yet to be incorporated into the master branch...need to wait? Because I trying to use Sketch / SketchPythonObject for Arch object, I drop into this 'shortcoming' and want this could change soon... thanks anyway.
I will give you my two cents.

There is a lot of functionality in realthunder's branch that is very nice and I personally would like to have in FreeCAD. Deciding whether it should be merged or not or to which extent depends on Werner. He is the code quality assurance department of FreeCAD (and God keeps it that way, otherwise people like my would destroy FreeCAD's codebase in less than a month :lol: ).

Unfortunately I do not think merging it will be straight-forward, first because the underlying philosophy seems to depart from what ickby had in mind (according to another thread), so this would probably require that the "gurus" agree on the future philosophy first. Second, provided that it is decided that realthunder's philosophy is to be followed without amendment, the amount of work he has put in is huge. This means the the work that Werner will have to do to review is huge too. Unfortunately we cannot clone Werner. So even then it would take a while.

All this to say that, to this specific issue you indicate, it is relatively easy to provide "a fix" (tm), but I think it is much more important to first know if realthunder's work will be merged or not and to which extent. If it is mergeable, which I hope it is, he already has the solution, and even in the case he hadn't a full solution, his work would have a lot of bearing on how "the right solution" (tm) should look like.

Short summary: This is a dead end until we know what will happen with realthunder's work.
paullee
Veteran
Posts: 5135
Joined: Wed May 04, 2016 3:58 pm

Re: sketch.Geometry[index].Tag == Unique identification survive changes?

Post by paullee »

abdullah wrote: Wed May 09, 2018 12:41 pm
Short summary: This is a dead end until we know what will happen with realthunder's work.
Hope someday we will have realthunder's works to merge!

I still try to write some codes to sync the geometry.tag and latest index. Kind of work :)

Thanks again anyway.
paullee
Veteran
Posts: 5135
Joined: Wed May 04, 2016 3:58 pm

Re: sketch.Geometry[index].Tag == Unique identification survive changes?

Post by paullee »

This is basically what is required.

Code: Select all


      self.EdgeTagListInitial = {}
      i = 0
      while True:
        try:
          tagI = fp.Geometry[i].Tag
          self.EdgeTagListInitial[tagI]=i
          i += 1
        except:
          break

Post Reply