How to improve efficiency about split surface by curves?

Dear all,

I want to split surface by curves.


I using RhinoSplitBrepFace() to split.
It cost about 10 min.
I using “Split” command to split the same model.
It only cost about 5 sec.
How can I improve efficiency?

The model in the 3dm file.
SplitSrfTest.3dm (578.2 KB)

Kind regards,
Vaker

The splitting performance, I think, is largely determined by the tolerance used. Are you sure you are using the same tolerance in both cases?

My code:

The FaceCount = 1 (only one surface to split)
dTol only one value to call function of RhinoSplitBrepFace() one times.

I’m sorry, I think my message is unclear.

The value of dTol - is it the same as the value of the model absolute tolerance when you run the Split command? If dTol << document tolerance (more strict), the split operation takes longer.

dTol is same as the value of the model absolute tolerance (1e-4)

double dTol = RhinoApp().ActiveDoc()->AbsoluteTolerance();

The sample code:

	CRhinoGetObject get1;
	get1.SetCommandPrompt(_T("Select surface to trim"));
	get1.SetGeometryFilter(CRhinoGetObject::surface_object);

	CRhinoGet::result rc1 = get1.GetObjects(1, 1);
	if (rc1 == CRhinoGetObject::cancel)
		return result::failure;
	if (get1.ObjectCount() == 0)
		return result::failure;

	CRhinoObjRef ObjRefSrf = get1.Object(0);
	const ON_Brep* pBrep = ObjRefSrf.Brep();

	CRhinoGetObject get2;
	get2.SetCommandPrompt(_T("Select curves to trim"));
	get2.SetGeometryFilter(CRhinoGetObject::curve_object);

	CRhinoGet::result rc2 = get2.GetObjects(1, 0);
	if (rc2 == CRhinoGetObject::cancel)
		return result::failure;
	if (get2.ObjectCount() == 0)
		return result::failure;

	ON_SimpleArray<const ON_Curve*> ArrCrvs;
	for (int index = 0; index<get2.ObjectCount(); index++)
	{
		CRhinoObjRef ObjRef = get2.Object(index);
		if (const ON_Curve* pCrv = ON_Curve::Cast(ObjRef.Geometry()))
		{
			ArrCrvs.Append(pCrv);
		}
	}

	::OutputDebugString(_T("Moldex3D-Mesh:: RhinoSplitBrepFace start"));

	ON_Brep* pOutBrep = NULL;
	double dTol = 1e-4;
	pOutBrep = RhinoSplitBrepFace(*pBrep, 0, ArrCrvs, dTol);

	::OutputDebugString(_T("Moldex3D-Mesh:: RhinoSplitBrepFace end"));

	if (pOutBrep == NULL)
		return result::failure;

	return CRhinoCommand::success;

Why RhinoSplitBrepFace() takes so long?

I ran your code on your file and it took pretty much exactly the same amount of time as the Rhino Split command. About 25 sec in a debug build. I was using the V6 WIP. Were you doing this in V5?

Yes, I was using Rhino 5.

I seem to remember a problem in V5 like this that was fixed in the past year or so. I don’t remember whether the fix made it into the V5 code, though. I don’t have V5 code on this computer but will check as soon as I can get on a machine with V5.

@dale I’m not sure I can do this in the next couple days. If you get to this before I do, I think the problem was that CPA.SplitAtIntersections( *srf, tolerance ); was inside the for loop rather than outside in RhinoSplitBrepFace()

@chuck, yes this fix is in the Rhino WIP and not Rhino 5. @Vaker, have you tried your code in the Rhino WIP?

– Dale

Hi Dale,

The feature is only in Rhino5.
Have any other solution to fix the problem (or pass around) in Rhino5?
Why the “Split” command has no performance problem in Rhino5?
Can I using the functions or procedures (used in “Split” command) to fix performance problem in Rhino5?
Thanks for your help.

Sorry, no, I don’t have any workarounds in V5.

Perhaps the Split command is not using RhinoSplitBrepFace

We are no longer working on Rhino 5. This is why I was hoping you’d try the Rhino WIP…

The functions used in “Split” command are not in Rhin5SDK.
So I can’t call the functions like “Split” command.
Is that right?

Hi Vaker,

Have you tried trimming the plane just using ON_Brep::NewPlanarFaceLoop?

– Dale

Hi Dale,

I used ON_Brep::NewPlanarFaceLoop() but nothing happened.

	ON_Plane Plane(ON_3dPoint(0.0,0.0,0.0), ON_3dVector(0.0,0.0,1.0));
	ON_PlaneSurface BasePlane(Plane);
	ON_Interval XAxis(90,115);
	ON_Interval YAxis(-3, 19);
	BasePlane.SetExtents(0, XAxis);
	BasePlane.SetExtents(1, YAxis);
	ON_Brep* pBrepCopy = BasePlane.BrepForm();

	if (pBrepCopy->NewPlanarFaceLoop(0, ON_BrepLoop::unknown, AddArrCrvs, false) == false)
		::OutputDebugString(_T("Moldex3D-Mesh:: NewPlanarFaceLoop failed"));

	::OutputDebugString(_T("Moldex3D-Mesh:: RhinoSplitBrepFace end"));

	CRhinoObjectManager OM;
	int iLayerIndex = OM.GetLayerIndex(_T("TrimSrf"));
	OM.AddOneBrepObject(*pBrepCopy, iLayerIndex);

There is nothing in “TrimSrf” layer.
I tried ON_BrepLoop::unknown、ON_BrepLoop::inner
Why?

With the sample model you originally posted, can you provide me a model of what you are looking to achieve. Some of the model’s curve are not closed, so its not clear to me what you want or expect…

– Dale

If you have a planer surface and you want to quickly punch a bunch of holes in it, then ON_Brep::NewPlanarFaceLoop can be quite useful. If the ‘hole’ curve are closed then you will need to add them one at a time.

I’ve attached a sample for you to review.

cmdTestVaker.cpp (3.0 KB)

– Dale

Hi Dale,

Thanks for your sample code.
It works.
I want to split complex case(not only single closed loop).
ON_Brep::NewPlanarFaceLoop can not split complex case.
I will try running “Split” command by scrip.