Trouble tracking parts of a body that is split by deleting faces

Trouble tracking parts of a body that is split by deleting faces

GRSnyder
Collaborator Collaborator
1,146 Views
8 Replies
Message 1 of 9

Trouble tracking parts of a body that is split by deleting faces

GRSnyder
Collaborator
Collaborator

I need to remove faces from a body (completely; that is, SurfaceDeleteFaceFeature, not DeleteFaceFeature) while keeping track of all the fragment bodies this operation might create.

 

For example, if you start with a solid cube and remove any belt of four faces, you end up with two surface bodies. I just want to be able to say, "Here are all the bodies that were modified or created by this SurfaceDeleteFaceFeature."

 

In theory, SurfaceDeleteFaceFeature has a 'bodies' property that supplies this exact information. However, in practice it seems to always be an empty list, whether the body splits or not. The 'faces' property is always empty as well.

 

The deletion itself seems to work fine and shows the correct results in the UI. The feature returns True for isValid.

 

I've tried a couple of other approaches, but so far nothing has yielded results. There's a vague suggestion in the docs that searching for the body's original entityToken might return multiple fragment bodies after a split, but I'm only getting zero or one object back. I also tried manually labeling the body with an attribute, but only one fragment retains the attribute after the split. Actually, the docs seem pretty explicit that splits should copy attribute values, so this makes me wonder if this sort of implicit backdoor split is bypassing the modeling kernel's normal split processing.

 

I suppose I could apply an attribute to all of the body's faces and then trace the faces back to their resulting bodies, but that's kind of ugly. Also, in the context I'm targeting, bodies might have thousands of faces. 

 

Any of this sound familiar? 

 

(Some additional details: This is in Python. The body whose faces are being deleted is an input to the process; I do not create it or modify it before the face deletion. Neither the original body nor the face-deletion feature is associated with a base feature. However, there is a base feature created (and then closed out) in the timeline between the point at which the body is created and the point at which faces are deleted. There are additional operations that precede the face deletion.)

0 Likes
Accepted solutions (1)
1,147 Views
8 Replies
Replies (8)
Message 2 of 9

BrianEkins
Mentor
Mentor
Accepted solution

The faces property is a property common to all features and returns the list of faces that were created by that feature so it makes sense that for a SurfaceDeleteFaceFeature it will always be empty because it never creates any faces.  The bodies property is also supported by all features but I would expect this to return the body the face was deleted from instead of being empty.  And ideally, return two bodies when the feature results in the body being split.

 

I also expected the entityToken to behave differently and return two bodies once the body was split. I don't know how the internals work in this case but I suspect this is a special case that's not accounted for in the entityToken code and also for attributes.

 

I think a workaround that can be implemented now is to get a list of all of the bodies in the component the input bodies is owned by and with each surface delete operation check to see if there's still the same number of bodies.  If not, find the new body and you'll have what you need.  The original body and the new body.  I believe the BRepBodies collection will return the bodies in the same order as they appear in the browser and in my quick test when I split the body the new body was added to the end of the list, not necessarily beside the original body. Assuming that is consistent it will be easy to monitor the number of bodies and then just get the last body when the number increases.

 

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
0 Likes
Message 3 of 9

GRSnyder
Collaborator
Collaborator

Thanks @BrianEkins, I will try the direct body inventory. That doesn't sound too painful.

 

I can likely generate some simple scripts that demonstrate the behavior of the 'bodies' property and the entityToken in this situation if that would be useful. I'll post them here.

0 Likes
Message 4 of 9

GRSnyder
Collaborator
Collaborator

I think part of my confusion here is that I've come to realize that there are really several completely independent spaces where bodies can exist:

 

  • Inside the TemporaryBRepManager
  • Inside a base feature within the parametric environment
  • Inside the general UI

If you create a body from scratch within a parametric document, you really need to promote it twice: once with Component.add and then again, implicitly, with baseFeature.finishEdit(). The three phases of the body are separate and immiscible and support different features, even though they're all BRepBodies. For example, bodies inside a base feature don't have attributes. They eventually come to support attributes when they are reified by closing the base feature, but by then they are different bodies.

 

Some features, such as Stitch and SurfaceDeleteFace, can be used both inside and outside a base feature. But those contexts, too, support different features. I think the issue mentioned in the original post is really better characterized as "SurfaceDeleteFaceFeature doesn't report its bodies when used inside a base feature." This seems to be common to most features.

 

Just for debugging, I'd like to reproduce my operation pipeline outside of a base feature just so I can poke and prod at every step and see where errors get introduced. But when the base feature that creates the original bodies is closed, the bodies assume new identities, and there's no obvious way to track them from inside to outside the base feature.

 

Diffing the body list has worked fine so far because I've been doing most of the work inside a base feature. All I really needed to know at the end was, "OK, what bodies are 'the results'?" But to move more features outside the base feature, I need a robust mapping from inside-base-feature bodies to outside-base-feature bodies, and there doesn't seem to be any direct way to obtain this information. I suppose I could generate a distinct base feature per body that is exported, but that seems a bit tortured. Either that, or characterize each body with some kind of hash based on its geometric particulars.

 

Is there a better way?

0 Likes
Message 5 of 9

Anonymous
Not applicable

You know, I should probably verify that entityToken and tempId don’t persist across the base feature boundary before whining on the Internet. Stay tuned..,

0 Likes
Message 6 of 9

GRSnyder
Collaborator
Collaborator

@Anonymous wrote: You know, I should probably verify that entityToken and tempId don’t persist across the base feature boundary before whining on the Internet. Stay tuned...

Woops, that was me again - must not have been logged in on that device.

 

Anyway, no dice. The entityToken is not preserved when closing the base feature, and design.findEntityByToken returns a zero-length list. tempIds on components of a BRepBody are not preserved either.

0 Likes
Message 7 of 9

kandennti
Mentor
Mentor

Hi @GRSnyder .

 

You just have to find the same surface before and after "SurfaceDeleteFaceFeature", right?

 

I have made a script in the past that compares two Step files to find the different faces.
It's all in Japanese, but here it is.

https://kantoku.hatenablog.com/entry/2018/10/04/124530 

 

It is done in the GetUnmatchedFaces function, but the algorithm is simple, and it only uses the center of gravity and surface area to find the faces that match. (Tolerance is important, so don't forget it.)

 

It's not fast, but I don't think it's terribly slow either.

 

0 Likes
Message 8 of 9

Anonymous
Not applicable

Edit: wrong account...

0 Likes
Message 9 of 9

GRSnyder
Collaborator
Collaborator

@kandennti wrote: I have made a script in the past that compares two Step files to find the different faces. It is done in the GetUnmatchedFaces function, but the algorithm is simple, and it only uses the center of gravity and surface area to find the faces that match. (Tolerance is important, so don't forget it.)

This is beautiful code - very clear. Thanks for the reference!

 

This is pretty much what I meant by a "hash of geometric features" above, but it's nice to have some code as a reference.

 

This does seem like a notable weakness of the API, though. It shouldn't be possible to lose track of bodies with no defined way to recover them other than making up your own ad-hoc heuristics.

 

[xxx make the post-bot happy xxx]

0 Likes