C++ Split brep with plane

Hi,

What is the method to split brep with plane in C++ sdk?

I found this sample file:

But it use other breps for splitting in this function *cutter is brep:
RhinoBrepSplit(*split, *cutter, tol, pieces)

Is there anything with plane splitting?

Hi @,

There is no SDK function that will split a Brep with a plane. If you have a plane, then create a plane surface, get it’s Brep form, and use it as the splitter.

Here is an sample, sans any error checking:

bool RhBrepSplit(
  const ON_Brep& brep,
  const ON_Plane& plane,
  double width,
  double height,
  double tolerance,
  ON_SimpleArray<ON_Brep*>& pieces,
  bool* bRaisedTol = nullptr
)
{
  ON_Interval d0, d1;
  d0.Set(0.0, width);
  d1.Set(0.0, height);

  ON_PlaneSurface* srf = new ON_PlaneSurface(plane);
  srf->SetExtents(0, d0, true);
  srf->SetExtents(1, d1, true);
  srf->SetDomain(0, d0.Min(), d0.Max());
  srf->SetDomain(1, d1.Min(), d1.Max());

  ON_Brep splitter;
  splitter.Create(srf); // splitter will delete srf...

  return RhinoBrepSplit(brep, splitter, tolerance, pieces, bRaisedTol);
}

– Dale

Thank you Dale.

Probably the width and the height of plane would be enough of brep bounding box diagonal length?

And could you please explain why in this and many other rhino menthods variables passed to fuction must be “const” ?

const means non-modifiable. In an API it generally means a promise the passed in object will not undergo any changes

https://www.cprogramming.com/tutorial/const_correctness.html

1 Like

Dear Dale,

Could please tell me what I am missing here when passing variables to RhinoBrepSplitPlane method?

The function returns true, but number of split breps are equal to 0:

bool RhinoBrepSplitPlane(
const ON_Brep& brep,
const ON_Plane& plane,
double tolerance,
ON_SimpleArray<ON_Brep*> pieces,
bool* bRaisedTol = nullptr
) {
	auto bbox = brep.BoundingBox();
	double length = bbox.Diagonal().Length();


	ON_Interval d0, d1;
	d0.Set(-length, length);
	d1.Set(-length, length);

	ON_PlaneSurface* srf = new ON_PlaneSurface(plane);
	srf->SetExtents(0,d0,true);
	srf->SetExtents(1, d1, true);
	srf->SetDomain(0,d0.Min(),d0.Max());
	srf->SetDomain(1,d1.Min(),d1.Max());



	ON_Brep splitter;
	splitter.Create(srf);//splitter will delete srf

	return RhinoBrepSplit(brep,splitter,tolerance,pieces,bRaisedTol);

}


CRhinoCommand::result CCommandLearning180704::RunCommand(const CRhinoCommandContext& context)
{


	//Get Geometry
	CRhinoGetObject g;
	g.SetCommandPrompt(L"Select Rectangle");
	g.SetGeometryFilter(CRhinoGetObject::curve_object);
	g.GetObjects(1, 1);

	//Check if it good
	if (g.CommandResult() != CRhinoCommand::success)
		return g.CommandResult();

	//Get first brep out of all breps
	const ON_Curve* curve = g.Object(0).Curve();

	//Check if it is good
	if (curve == 0)
		return CRhinoCommand::failure;


	//Try get Polyline
	ON_SimpleArray< ON_3dPoint > points;
    int n = curve->IsPolyline(&points);

	if (n == 5) {

		//Get plane from 5 points polyline

		//Get Center
		ON_3dPoint basePt(0, 0, 0);
		for (int i = 0; i < n - 1; i++) 
			basePt += points[i];
		basePt /= n - 1;

		//Get xdir and ydir
		ON_3dVector vec0 = points[0] - points[1];
		ON_3dVector vec1 = points[0] - points[n - 2];
		vec0.Unitize();
		vec1.Unitize();

		//Construct plane
		const ON_Plane cutPlane(basePt, vec0, vec1);


		//Get Brep and split it https://developer.rhino3d.com/samples/cpp/split-brep/
		// Pick the brep to split
		CRhinoGetObject go;
		go.SetCommandPrompt(L"Select surface or polysuface to split");
		go.SetGeometryFilter(CRhinoGetObject::surface_object | CRhinoGetObject::polysrf_object);
		go.GetObjects(1, 1);
		if (go.CommandResult() != success)
			return go.CommandResult();

		const CRhinoObjRef& split_ref = go.Object(0);

		const CRhinoObject* split_object = split_ref.Object();
		if (!split_object)
			return failure;

		const ON_Brep* split = split_ref.Brep();
		if (!split)
			return failure;

	


		ON_SimpleArray<ON_Brep*> pieces;
		double tol = context.m_doc.AbsoluteTolerance();


		bool flag = RhinoBrepSplitPlane(*split, cutPlane, tol, pieces);//Split method <--------------------

		int i, count = pieces.Count();
		if (count == 0 | count == 1)
		{
			if (count == 1)
				delete pieces[0];
			RhinoApp().Print(L"Nothing %d, %d.\n", count, flag);
			return nothing;
		}

		CRhinoObjectAttributes attrib = split_object->Attributes();
		attrib.m_uuid = ON_nil_uuid;

		const CRhinoObjectVisualAnalysisMode* vam_list = split_object->m_analysis_mode_list;

		for (i = 0; i < count; i++)
		{
			CRhinoBrepObject* brep_object = new CRhinoBrepObject(attrib);
			if (brep_object)
			{
				brep_object->SetBrep(pieces[i]);
				if (context.m_doc.AddObject(brep_object))
					RhinoCopyAnalysisModes(vam_list, brep_object);
				else
					delete brep_object;
			}
		}



		context.m_doc.DeleteObject(split_ref);
		context.m_doc.Redraw();



	}


	
	return CRhinoCommand::success;


	return success;
}

Solved.

I typed:

bool RhinoBrepSplitPlane(
const ON_Brep& brep,
const ON_Plane& plane,
double tolerance,
ON_SimpleArray<ON_Brep*> pieces,
bool* bRaisedTol = nullptr
) {

Instead of

bool RhinoBrepSplitPlane(
const ON_Brep& brep,
const ON_Plane& plane,
double tolerance,
ON_SimpleArray<ON_Brep*>& pieces,
bool* bRaisedTol = nullptr
) {

So it was not modifying brep by reference.

Dear Dale,

I was playing with this brep split function:

I would like to ask if it is possible to achieve something as interactive with rhino as this mirror cut script in maya.
I basically want to move rectangle around and execute brep split method interactively (while moving rectangle)
Instead of ctrl+z and repeating the command.
Any reference you could give or describe how this kind of interactive workflow could be made?

I also tried to turn record history on, but it did not work.

Hi @Petras_Vestartas,

I watched the video, admittedly not that closely. It looks like the script just mirrors meshes. Perhaps I am confused.

If you use Rhino’s build-in gumball, it might not take too much to put a similar tool together. I you plan on using a custom gumball, it would take more work, obviously.

Also, if you want to support history, you need to modify your command to record it. The samples repo has a couple of history-supporting command samples. Here is one.

https://github.com/mcneel/rhino-developer-samples/blob/6/cpp/SampleCommands/cmdSampleHistoryDivide.cpp

– Dale

Dear @dale,

Yes it is nothing more than splitting geometry and mirroring it.

The most complicated part it seems the UI, epsecially when you mention using Rhino Gumball.
Is the any guide for this sort of live update using Gumball?

Hi @Petras_Vestartas,

There are a couple of SDK samples that use the gumball.

https://github.com/mcneel/rhino-developer-samples

– Dale

Thank you Dale