Cancel
Showing results for 
Search instead for 
Did you mean: 

Curve Break - NURBS surface workaround

Experimenter
Experimenter

Request: curve break tool that works on NURBS / Bsurfs

 

Scope: aero meshes, pressure interpolation & mapping.

Task: Break a curve.

Limitations: NURBS / Boundary Surface

 

Often I encounter a situation adjusting a mesh where I need to break a curve that is utilized to define a boundary or NURBS surface. I am aware of NURBS surface definition and why this cannot be done simply using the Curve-->Break tool.

 

Solution: Brute force API:

  1. Use curve break tool routine
  2. Elevate to run macro when tool cannot break curve :
  3. Grab assosciated curves and surfaces around selected point(s) 
  4. Kill BSurf / NURBS dependencies. Preserve mesh / curve attributes & ID's.
  5. Delete relevant surfaces, break curves, add in broken curve ID(s)
  6. Re-create Bsurfs, assign original properties & attributes
  7. Preserve undo mem. so mess-ups are easily resolved.

Attached is a test model and 95% complete macro. Any help is appreciated.

My macro is failing to re-update the BSurf definition with appended curve break ID. So close!!

 

 My attempt looks about like this: Code fails to PUT curve ID's into surf object.

Sub Main()
	Dim App As femap.model
    Set App = feFemap()

    Dim tempSet As femap.Set
    Dim trimCurves As femap.Set
	Dim curveSet As femap.Set
	Dim pointSet As femap.Set
	Dim surfSet As femap.Set
	Dim feSurf As femap.Surface
	Dim feCurve As femap.Curve
	Dim fePt As femap.Point
	Dim curveUserData As femap.UserData

	Set trimCurves = App.feSet()
	Set curveSet = App.feSet()
	Set pointSet = App.feSet()
	Set feSurf = App.feSurface()
	Set feCurve = App.feCurve()
	Set fePt  = App.fePoint()
	Set surfSet = App.feSet()
	Set tempSet = App.feSet()
	Set curveUserData = App.feUserData()

	Dim pointID As Long
	Dim numID As Long
	Dim surfCount As Long
	Dim curveCount As Long
	Dim rc As Variant
	Dim numCurves As Long
	Dim vCurveID As Variant
	Dim curveID As Long
	Dim curveBreakID As Long
	Dim j,k As Long

	'SURFACE PROPS
	Dim surfID() As Long
	Dim sLayer() As Long
	Dim sColor() As Long
	Dim sType() As Long
	Dim vStdCurve() As Variant
	Dim vStdCurveReverse() As Variant
	Dim vDivisions() As Variant
	Dim sEngine() As Long
	Dim sAddress() As Long
	Dim Suppressed() As Boolean

	'MESH ATTRIBUTES
	Dim attrPID() As Long
	Dim attrTopology() As Long
	Dim attrMesher() As Long
	Dim attrMappedLevel() As Long
	Dim attrMapSubdivisions() As Boolean
	Dim attrMapEqualOnly() As Boolean
	Dim attrMapAltTri() As Boolean
	Dim attrMapRightBias() As Boolean
	Dim attrMapSplitQuads() As Boolean
	Dim attrMapAngleDeviation() As Double
	Dim attrMapMinCornerAngle() As Double
	Dim attrMidsidegeom() As Boolean
	Dim attrMidsideAngle() As Double
	Dim attrMinBetween() As Long
	Dim attrMaxAspect() As Double
	Dim attrQuickCutNodes() As Long
	Dim attrQuadCutAngle() As Double
	Dim attrSmoothLaplacian() As Boolean
	Dim attrSmoothIter() As Long
	Dim attrSmoothTolerance() As Double
	Dim attrConnectEdgeNodes() As Boolean
	Dim attrConnectEdgeNodeTol() As Double
	Dim attrOffsetFrom() As Long
	Dim attrOffset() As Double
	Dim attrInitialized() As Boolean
	Dim attrPostMeshCleanup() As Boolean
	Dim QuadMeshLayers() As Long

	'MESH APPROACH
	Dim sApproach() As Long
	Dim vApproachData() As Variant

	'MESH SIZING
	Dim MeshSizeInterior() As Double
	Dim MeshSizeChord() As Double

	'FOR MESH POINTS ON SURFACE
	Dim vMeshPoint() As Variant

	'BOUNDARY SURFACE ONLY ---
	Dim vBoundaryCurve() As Variant
	Dim vBoundaryFlag() As Variant
	Dim BoundaryMode() As Long
	Dim BoundaryOnSurface() As Long

	Dim surfCurves() As Variant
	Dim a() As Long
	Dim surfCurveCount() As Long

	rc = curveSet.Select(FT_CURVE, True,"Select Curve(s) to Break")
	rc = pointSet.SelectID(FT_POINT,"Enter Location to Break at",pointID)
	rc = fePt.Get(pointID)
	rc = curveSet.Reset()

	While curveSet.Next()
		rc = feCurve.Get(curveSet.CurrentID)
		rc = surfSet.AddRule(feCurve.ID,FGD_SURFACE_BYCURVE)
	Wend
	surfCount = surfSet.Count()

	If surfCount >0 Then
		ReDim surfID(1 To surfCount)
		ReDim sLayer(1 To surfCount)
		ReDim sColor(1 To surfCount)
		ReDim sType(1 To surfCount)
		ReDim vStdCurve(1 To surfCount)
		ReDim vStdCurveReverse(1 To surfCount)
		ReDim vDivisions(1 To surfCount)
		ReDim sEngine(1 To surfCount)
		ReDim sAddress(1 To surfCount)
		ReDim Suppressed(1 To surfCount)
		ReDim attrPID(1 To surfCount)
		ReDim attrTopology(1 To surfCount)
		ReDim attrMesher(1 To surfCount)
		ReDim attrMappedLevel(1 To surfCount)
		ReDim attrMapSubdivisions(1 To surfCount)
		ReDim attrMapEqualOnly(1 To surfCount)
		ReDim attrMapAltTri(1 To surfCount)
		ReDim attrMapRightBias(1 To surfCount)
		ReDim attrMapSplitQuads(1 To surfCount)
		ReDim attrMapAngleDeviation(1 To surfCount)
		ReDim attrMapMinCornerAngle(1 To surfCount)
		ReDim attrMidsidegeom(1 To surfCount)
		ReDim attrMidsideAngle(1 To surfCount)
		ReDim attrMinBetween(1 To surfCount)
		ReDim attrMaxAspect(1 To surfCount)
		ReDim attrQuickCutNodes(1 To surfCount)
		ReDim attrQuadCutAngle(1 To surfCount)
		ReDim attrSmoothLaplacian(1 To surfCount)
		ReDim attrSmoothIter(1 To surfCount)
		ReDim attrSmoothTolerance(1 To surfCount)
		ReDim attrConnectEdgeNodes(1 To surfCount)
		ReDim attrConnectEdgeNodeTol(1 To surfCount)
		ReDim attrOffsetFrom(1 To surfCount)
		ReDim attrOffset(1 To surfCount)
		ReDim attrInitialized(1 To surfCount)
		ReDim attrPostMeshCleanup(1 To surfCount)
		ReDim QuadMeshLayers(1 To surfCount)
		ReDim sApproach(1 To surfCount)
		ReDim vApproachData(1 To surfCount)
		ReDim MeshSizeInterior(1 To surfCount)
		ReDim MeshSizeChord(1 To surfCount)
		ReDim vMeshPoint(1 To surfCount)
		ReDim vBoundaryCurve(1 To surfCount)
		ReDim vBoundaryFlag(1 To surfCount)
		ReDim BoundaryMode(1 To surfCount)
		ReDim BoundaryOnSurface(1 To surfCount)

		ReDim surfCurves(1 To surfCount)
		ReDim surfCurveCount(1 To surfCount)
	End If

	App.feAppMessage(FCM_ERROR,"SURFACE ATTRIBUTES SUBROUTINE:")

	surfSet.Reset()
	i =0
	While surfSet.Next()
		i =i+1
		rc = feSurf.Get(surfSet.CurrentID)
		With feSurf
			surfID(i) = .ID
			sLayer(i) = .layer
			sColor(i) = .color
			sType(i) = .type
			vStdCurve(i) = .vStdCurve
			vStdCurveReverse(i) = .vStdCurveReverse
			vDivisions(i) = .vDivisions
			sEngine(i) = .Engine
			sAddress(i) = .Address
			Suppressed(i) = .Suppressed
			attrPID(i) = .attrPID
			attrTopology(i) = .attrTopology
			attrMesher(i) = .attrMesher
			attrMappedLevel(i) = .attrMappedLevel
			attrMapSubdivisions(i) = .attrMapSubdivisions
			attrMapEqualOnly(i) = .attrMapEqualOnly
			attrMapAltTri(i) = .attrMapAltTri
			attrMapRightBias(i) = .attrMapRightBias
			attrMapSplitQuads(i) = .attrMapSplitQuads
			attrMapAngleDeviation(i) = .attrMapAngleDeviation
			attrMapMinCornerAngle(i) = .attrMapMinCornerAngle
			attrMidsidegeom(i) = .attrMidsideGeom
			attrMidsideAngle(i) = .attrMidsideAngle
			attrMinBetween(i) = .attrMinBetween
			attrMaxAspect(i) = .attrMaxAspect
			attrQuickCutNodes(i) = .attrQuickCutNodes
			attrQuadCutAngle(i) = .attrQuadCutAngle
			attrSmoothLaplacian(i) = .attrSmoothLaplacian
			attrSmoothIter(i) = .attrSmoothIter
			attrSmoothTolerance(i) = .attrSmoothTolerance
			attrConnectEdgeNodes(i) = .attrConnectEdgeNodes
			attrConnectEdgeNodeTol(i) = .attrConnectEdgeNodeTol
			attrOffsetFrom(i) = .attrOffsetFrom
			attrOffset(i) = .attrOffset
			attrInitialized(i) = .attrInitialized
			attrPostMeshCleanup(i) = .attrPostMeshCleanup
			QuadMeshLayers(i) = .QuadMeshLayers
			sApproach(i) = .approach
			vApproachData (i) = .vapproachData
			MeshSizeInterior(i) = .MeshSizeInterior
			MeshSizeChord(i) = .MeshSizeChord
			vMeshPoint(i) =.vMeshPoint
			vBoundaryCurve(i) = .vBoundaryCurve
			vBoundaryFlag(i) = .vBoundaryFlag
			BoundaryMode(i) = .BoundaryMode
			BoundaryOnSurface(i) = .BoundaryOnSurface
		End With

		App.feAppMessage(FCM_NORMAL," Surface" & Str(feSurf.ID) & " Attributes stored locally...")
		tempSet.Clear()

		rc = feSurf.Curves(0,numCurves,vCurveID)
		surfCurves(i) = vCurveID
		surfCurveCount(i) = numCurves


		'------------------------temporary debug section------------------------
		Dim count As Long

		tempSet.AddArray(count,vBoundaryFlag(i))

		tempSet.Reset()
		App.feAppMessage(FCM_ERROR, "DEBUGGING SURF CURVES")
		While tempSet.Next()
			App.feAppMessage(FCM_HIGHLIGHT,Str(tempSet.CurrentID))
		Wend

		tempSet.Clear()


		'------------------------temporary debug section------------------------

		tempSet.AddArray(numCurves,vCurveID)


		rc = trimCurves.AddCommon(tempSet.ID,curveSet.ID)
		rc = feSurf.Delete(feSurf.ID)
		tempSet.Clear()

	Wend
	App.feAppMessage(FCM_NORMAL, "LISTING SELECTED TRIM CURVES:")
	trimCurves.Debug()

	App.feAppMessage(FCM_NORMAL,"")
	App.feAppMessage(FCM_NORMAL,"")
	App.feAppMessage(FCM_NORMAL,"")



	i=0

	surfSet.Clear()
	curveSet.Clear()

	App.feAppMessage(FCM_ERROR,"CURVE TRIM SUBROUTINE:")
	trimCurves.Reset()
	While trimCurves.Next()
		rc = feCurve.Get(trimCurves.CurrentID)
		curveID = feCurve.ID
		curveBreakID = App.Info_NextID(FT_CURVE)

		curveSet.AddAll(FT_CURVE)
		j = curveSet.Count()

		rc = App.feCurveBreak(curveID,fePt.xyz)

		'add an if statement here to handle errors like point projection not on curve =trim fails
		curveSet.AddAll(FT_CURVE)
		k = curveSet.Count()

		If j <k Then 'a new curve was created...
			App.feAppMessage(FCM_NORMAL,"curve created")
			App.feAppMessage(FCM_NORMAL,"TRIM REVIEW:")
			App.feAppMessage(FCM_NORMAL,"Broken Curve ID = " & curveBreakID)
			App.feAppMessage(0,"Original Curve ID: " & Str(curveID)  _
					& "  - After Break: " & Str(curveBreakID) & " + " &  Str(curveID))
			App.feAppMessage(FCM_NORMAL,"")

			'add a loop for surfcount in here, add surfcurves(i) to tempset
			For i = 1 To surfCount
				rc = tempSet.AddArray(surfCurveCount(i),surfCurves(i))

				If rc = -1 Then

					App.feAppMessage(FCM_NORMAL,"Surface ID: " & Str(surfID(i)))
					App.feAppMessage(FCM_NORMAL,"Loaded surfcurves into tempSet:")
					tempSet.Debug()
					'OK, it's properly remembering the original surface curves here.

					'check if CurveID in CURRENT LOOP is in tempSet... if YES then also add CurveBreakID
					rc = tempSet.IsAdded(curveID)
					If rc = -1 Then
						App.feAppMessage(FCM_NORMAL, "Surface " & Str(surfID(i)) & " added curve " & Str(curveBreakID) & " to boundary.")
						'add curvebreak to tempset here
						tempSet.Add(curveBreakID)
						App.feAppMessage(FCM_NORMAL,"Listing boundary surfaces for new surface:")
						'add 1 to surf curve count
						surfCurveCount(i) = surfCurveCount(i) +1
						tempSet.Debug()
						tempSet.Reset()

						Dim num As Long
						Dim varray As Variant

						rc = tempSet.GetArray(num,varray)
						surfCurves(i) = varray


					Else
						App.feAppMessage(FCM_NORMAL,"Current trim curve " & Str(curveID) & " is not part of surface " & Str(surfID(i)))
					End If

				End If
				tempSet.Clear()
				App.feAppMessage(FCM_NORMAL,"")
			Next

		Else
			App.feAppMessage(FCM_ERROR,"curve not created")
		End If

	Wend

	App.feAppMessage(FCM_NORMAL,"")
	App.feAppMessage(FCM_NORMAL,"")
	App.feAppMessage(FCM_NORMAL,"")


	'free the surf memory & then rebuild
	Set feSurf = Nothing
	Set feSurf = App.feSurface

	App.feAppMessage(FCM_HIGHLIGHT,"Surfcount = " & Str(surfCount))

	App.feAppMessage(FCM_ERROR,"SURFACE REBUILD SUBROUTINE:")
	For i = 1 To surfCount
		'rebuild
		App.feAppMessage(FCM_HIGHLIGHT,"Rebuilding Surface " & Str(surfID(i)))
		'message the boundary curves to construct surface here
		rc = feSurf.Put(surfID(i))
		rc = feSurf.Get(surfID(i))

		With feSurf
			'assign attributes here
			.ID = surfID(i)
			.layer = sLayer(i)
			.color =sColor(i)
			.type = sType(i)
			.vStdCurve = vStdCurve(i)
			.vStdCurveReverse = vStdCurveReverse(i)
			.vDivisions = vDivisions(i)
			.Engine = sEngine(i)
			.Address = sAddress(i)
			.Suppressed = Suppressed(i)
			.attrPID = attrPID(i)
			.attrTopology = attrTopology(i)
			.attrMesher = attrMesher(i)
			.attrMappedLevel = attrMappedLevel(i)
			.attrMapSubdivisions = attrMapSubdivisions(i)
			.attrMapEqualOnly = attrMapEqualOnly(i)
			.attrMapAltTri = attrMapAltTri(i)
			.attrMapRightBias = attrMapRightBias(i)
			.attrMapSplitQuads = attrMapSplitQuads(i)
			.attrMapAngleDeviation = attrMapAngleDeviation(i)
			.attrMapMinCornerAngle = attrMapMinCornerAngle(i)
			.attrMidsideGeom = attrMidsidegeom(i)
			.attrMidsideAngle = attrMidsideAngle(i)
			.attrMinBetween = attrMinBetween(i)
			.attrMaxAspect = attrMaxAspect(i)
			.attrQuickCutNodes = attrQuickCutNodes(i)
			.attrQuadCutAngle = attrQuadCutAngle(i)
			.attrSmoothLaplacian = attrSmoothLaplacian(i)
			.attrSmoothIter = attrSmoothIter(i)
			.attrSmoothTolerance = attrSmoothTolerance(i)
			.attrConnectEdgeNodes = attrConnectEdgeNodes(i)
			.attrConnectEdgeNodeTol = attrConnectEdgeNodeTol(i)
			.attrOffsetFrom = attrOffsetFrom(i)
			.attrOffset = attrOffset(i)
			.attrInitialized = attrInitialized(i)
			.attrPostMeshCleanup = attrPostMeshCleanup(i)
			.QuadMeshLayers = QuadMeshLayers(i)
			.approach = sApproach(i)
			.vapproachData = vApproachData (i)
			.MeshSizeInterior = MeshSizeInterior(i)
			.MeshSizeChord = MeshSizeChord(i)
			.vMeshPoint = vMeshPoint(i)


			.vBoundaryCurve =surfCurves(i)
			'.vBoundaryCurve = vBoundaryCurve(i)

			.vBoundaryFlag = vBoundaryFlag(i)
			.BoundaryMode = BoundaryMode(i)
			.BoundaryOnSurface = BoundaryOnSurface(i)

			.Put(surfID(i))
		End With
	Next
App.feViewRegenerate(0)
End Sub