Showing results for 
Search instead for 
Do you mean 
Solved! Go to solution

API: Face Splitting - How to Avoid Trimming Curves

[ Edited ]

Hello - This is a separate, but related to, my other API face splitting post (here if interested).  This is a separate challenge that I am encountering that I think warrants a second post.  I am ultimately interested in writing a script that mimics Geometry > Curves from Surface > Project (i.e. face splitting).  The intent is to also track the "child" surfaces that result from splitting of each "parent" surface and to be able to tie the children back to each parent. 


The issue is that with the API version of Project, feCurveProjectOntoSurface, all of the selected parent surfaces are split at once with all of the selected curves, making tracking impossible.


I thought that if I could allow the user to select all of the parent surfaces to split and all of the curves to split with and then control the flow of the surface to the feCurveProjectOntoSurface by passing them one at a time, I could then use the feTrackData object to collect the new child surface IDs. 


The idea is that you pass a single surface at a time with all of the splitting curves to feCurveProjectOntoSurface, then scoop up the new child surfaces and split those children with all of the splitting curves, continuing until there are no more resultant child surfaces from that parent.  Then you move onto the next parent.


The problem is  that after the very first split of the very first parent, the splitting curves are trimmed so that you cannot continue to split the child surfaces with them.  There is no flag that I can set to turn off trimming, so I am at a loss as to how I proceed. 


The code below functions, but since the trimming occurs, it does not perform the way I want.


Observe the following 2 surfaces (1 rectangle + 1 circle):



If I add the following curves (criss-crossed):



And split through the GUI I get the expected 12 surfaces:


But if I split only the rectangle with all of the curves through the GUI, we see that the original curves get trimmed and so they are no longer available to split the circle:



I get the same the same result running my code and selecting both surfaces and all of the curves (since it passes them one at a time to the same method the GUI uses).


Sub Main
	Dim App As femap.model
  	Set App = feFemap()
	Dim rc As Long					'return code
	Dim pSet As Set					'set of parent surfaces
	Set pSet = App.feSet		
	Dim cSet As Set					'set of child surface that arise from splitting
	Set cSet = App.feSet
	Dim splitSet As Set			'set of child surfaces to split again
	Set splitSet = App.feSet
	Dim oldSplitSet As Set			'tmp set
	Set oldSplitSet = App.feSet
	Dim sid As Long					'surface ID
	Dim cuSet As Set				'curve set for splitting
	Set cuSet= App.feSet
	Dim normv As Variant			'normal vector; never used
	Dim baseXYZ(3) As Double		'never used but needed by vector method
	Dim baseXYZv As Variant
	Dim newGeom As femap.TrackData	'tracks newly created objects
	Set newGeom = App.feTrackData
	Dim sngSet As Set				'used to control splitting to single surf
	Set sngSet = App.feSet
	Dim newCount As Long	'count new surfs

	'use arbitrary point as base of unit norm
	baseXYZ(0) = 0.0
	baseXYZ(1) = 0.0
	baseXYZ(2) = 0.0
	'convert to variant for use in methods
	baseXYZv = baseXYZ

	'select surfs to split
	rc = pSet.Select(FT_SURFACE,True, "Select surfaces to split")
	'select curves to split with
	rc = cuSet.Select(FT_CURVE, True, "Select curves to split with")
	'set norm first surf normal (not used but nds intialization for code to run)
	rc = App.feVectorNormalToSurface(pSet.First(), baseXYZv, normv)
	'set flag to update surfaces as true else surfs will not be split

	pSet.Reset()		'reset internal pointer
	sid = pSet.Next()
	'splitting routine
	Do While sid <> 0
		rc = sngSet.Add(sid)	'pass one surf to sngSet
		cSet.Clear()					'clear the child surf set
		newGeom.Start(FT_SURFACE)	'turn on new surf tracking
		'split the SINGLE parent surface with all curves
		rc = App.feCurveProjectOntoSurfaces(True, normv, sngSet.ID, cuSet.ID, True) 'the curves get trimmed here which botches the deal
		'append newly created surf IDs to set; this also turns off tracking
		newGeom.Created(FT_SURFACE, cSet.ID, False)

		newCount = cSet.Count()		'count new surfs
		splitSet.AddSet(cSet.ID)		'initialize split set to child set
		'split children
		Do While newCount <> 0
			newGeom.Start(FT_SURFACE)		'turn tracking back on
			'split ALL child surfaces with all curves
			rc = App.feCurveProjectOntoSurfaces(True, normv, splitSet.ID, cuSet.ID, True)
			newGeom.Created(FT_SURFACE, cSet.ID, False)		'append new surfs
			newCount = cSet.Count() - newCount
			'reduce splitset to only the newest surfs
			splitSet.AddSet(cSet.ID)		'full set
			splitSet.Remove(oldSplitSet.ID)		'remove prior iterations' sets

		sngSet.Clear()		'empty sngSet for next round
		sid = pSet.Next()	'get next parent


End Sub

Any suggestions would be greatly appreciated. How can I arrive at the same result as in the image with 12 surfaces, but by passing the surfaces one at a time so I can track new objects? Is it futile?

Accepted by topic author saladsamurai
‎04-04-2016 11:00 AM

Re: API: Face Splitting - How to Avoid Trimming Curves

You can always copy the original curves to a new set using get and put or use feGenerateCopy and the feTrackData object to get the IDs of the copied curves to the copied and use the copied set ID for the feCurveProjectOntoSurface function.  You would use the ID of the copiedCurves set instead of the cuSet ID as the argument for rc = App.feCurveProjectOntoSurfaces(True, normv, splitSet.ID, copiedCurves.ID, True)

Examples of the code are below.



If you use Get and Put you can use this code to copy into the new set:


   Dim copiedCurves as femap.set

   Set copiedCurves = app.feset

   Dim cu as femap.Curve

   Set cu = app.feCurves

   Dim cuID as Long

   Dim newID as Long


Inside your Do While loop then add:



  cuID = cuSet.first

  For ii = 0 to cuSet.count-1

    cu.get (cuID)

    cuID = app.feCurve.NextEmptyID

    cu.put ( cuID )

    copiedCurves.add ( cuID )

    cuID = cu.Next

 Next ii



If you use the feTrackData object then you can copy the curves using the following:


   Dim translateV as variant

   translateV = baseXYZ

   Dim copiedCurves as femap.set

   Set copiedCurves = app.feset

   Dim copyCu as femap.TrackData

   Set copyCu = app.feTrackData


Inside your Do While loop then add:





  rc =App.feGenerateCopy ( FT_CURVE, cuSet.ID, translateV, 1, True )


  copyCu.Created ( FT_CURVE, copiedCurves.ID, False )

Best Regards,
Chip Fricke
Principal Applications Engineer - Femap Product Development

Re: API: Face Splitting - How to Avoid Trimming Curves

Are you aware of File -> Preferences -> Geometry ... Construction Geometry?  

The default is that your curves are deleted because they are considered as "construction geometry" (unless, of course, they belonged to another surface/solid).  Anyway, if you set that preference to "Do Nothing", then the curves you use to project are not deleted when the first projection is done.  In this case, then you can loop through multiple projections whilst continuing to use the same set of curves to project.

Note, however, that I believe the default preference is the "tidiest" to avoid inadvertent multiple curves in the same location, so you may wish to consider changing the preference temporarily, and then changing it back to the default at the end of your API.

Also note that the projection curves aren't "trimmed".  The "printed on" curves are brand new, whilst the projected curves are entirely deleted due to the above preference.  If you change the above preference to "Do Nothing", then you will have the new printed on curves as well as the original curves you used as the projection curves.

Re: API: Face Splitting - How to Avoid Trimming Curves

[ Edited ]

Thanks Chip! I am not sure why I did not think of copying curves.  I will need to test this out and get back to you with some questions I have.


Edit: I am not sure why this is showing up under EndZ's response as I am replying to yours!


EndZ: Thanks for the input.  Do you know if there is a way to set this preference programatically? If yes, this may be another good option.

Re: API: Face Splitting - How to Avoid Trimming Curves

Section of the API.PDF: Pref_ConstructionGeometry

Re: API: Face Splitting - How to Avoid Trimming Curves

Chip - Could you just clarify something for me: It sounds like you are presenting 2 different ways of accomplishing this:
1) use Get and Put
2) use feGenerateCopy and feTrackData.

Re: API: Face Splitting - How to Avoid Trimming Curves

Instead of App.feCurveProjectOntoSurfaces, try feCurveProjectCurvesOntoSurfaces, it uses the code the Meshing Toolbox's Geometry Editing, Project Curve, and its options.  It will shoot all the curves onto the selected surface or surfaces and they will all get burned in.



Re: API: Face Splitting - How to Avoid Trimming Curves

I was presenting two different ways to copy entities.  I generally use the Get/Put method only when I'm copying a single entity or an entity type not supported by the feGenerateCopy function.  The feGenerateCopy function in conjunction with the feTrackData object is the best method for copying multiple entities.


Best Regards,
Chip Fricke
Principal Applications Engineer - Femap Product Development

Re: API: Face Splitting - How to Avoid Trimming Curves

Thanks again Chip!  I was able to solve my issues using feGenerateCopy and tracking.  Once my code is polished up a little, I will post it here in case it is useful to anyone. 


It replicates the Curve-From Surface face splitting functionality with the addition that any "child" surfaces created will be put into any groups that originally contained the "parent" surface that was split.