Site Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

developer:sdksamples:tightboundingbox [2015/09/14] (current)
Line 1: Line 1:
 +====== Calculating Tight Bounding Boxes for Breps ======
 +> **Developer:​** //​[[developer:​dotnetplugins|.NET]]//​
 +> **Summary:​** //Discusses the calculation of tight bounding boxes and Brep objects.//
 +> **NOTICE:** //The Rhino.NET SDK is deprecated in Rhino 5.  This example adapted for the new RhinoCommon SDK is [[developer:​rhinocommonsamples:​tightboundingbox|here]]//​
 +===== Question =====
 +I am having a problem with getting a tight bounding box of a trimmed ​
 +Brep using C#. I have a trimmed surface which I then split into smaller pieces. I then want to get each face of this new Brep and get the bounding box of each. However, each of the resulting bounding boxes bounds the extent of the original Brep and not the individual faces. If I extract the edge loop, this bounds correctly, however.
 +
 +===== Answer =====
 +Tight bounding boxes for surfaces and Breps are calculated with runtime ​
 +information,​ such as display curves and render meshes. Thus, when you cook 
 +up your own Brep, which do not have display curves and render meshes, you 
 +only get the bounding boxes of the untrimmed surfaces.
 +
 +One way round this is to call **RhUtil.RhinoGetTightBoundingBox**. This function ​
 +requires Rhino objects that are in the document. This is probably not too 
 +convenient in your situation.
 +
 +Another alternative is to created meshes, one for each Brep face, and then 
 +calculate the bounding box of each mesh. This should give you accurate ​
 +results.
 +
 +==== C# ====
 +
 +<code c#>
 +public override IRhinoCommand.result RunCommand(IRhinoCommandContext context)
 +{
 +  MRhinoGetObject gs = new MRhinoGetObject();​
 +  gs.SetCommandPrompt("​Select surface to split"​);​
 +  gs.SetGeometryFilter(IRhinoGetObject.GEOMETRY_TYPE_FILTER.surface_object);​
 +  gs.GetObjects(1,​1);​
 +  if (gs.CommandResult() != IRhinoCommand.result.success)
 +    return gs.CommandResult();​
 +
 +  IOnBrep brep = gs.Object(0).Brep();​
 +  if (null == brep)
 +    return IRhinoCommand.result.failure;​
 +
 +  MRhinoGetObject gc = new MRhinoGetObject();​
 +  gc.SetCommandPrompt("​Select cutting curve"​);​
 +  gc.SetGeometryFilter(IRhinoGetObject.GEOMETRY_TYPE_FILTER.curve_object);​
 +  gc.EnablePreSelect(false);​
 +  gc.EnableDeselectAllBeforePostSelect(false);​
 +  gc.GetObjects(1,​1);​
 +  if (gc.CommandResult() != IRhinoCommand.result.success)
 +    return gc.CommandResult();​
 +
 +  IOnCurve[] cutters = new IOnCurve[1];​
 +  cutters[0] = gc.Object(0).Curve();​
 +  if (null == cutters[0])
 +    return IRhinoCommand.result.failure;​
 +
 +  OnBrep split_brep = RhUtil.RhinoSplitBrepFace(brep,​ 0, cutters, context.m_doc.AbsoluteTolerance() );
 +  if (null == split_brep)
 +  {
 +    RhUtil.RhinoApp().Print("​Unable to split surface.\n"​);​
 +    return IRhinoCommand.result.nothing;​
 +  }
 +
 +  IOnMeshParameters mp = context.m_doc.Properties().RenderMeshSettings();​
 +  OnMesh[] mesh_list = new OnMesh[0];
 +  int mesh_count = split_brep.CreateMesh(mp,​ ref mesh_list);
 +
 +  int num_added = 0;
 +  for (int i = 0; i < mesh_list.Length;​ i++)
 +  {
 +    OnBoundingBox bbox = new OnBoundingBox();​
 +    if (mesh_list[i].GetTightBoundingBox(ref bbox))
 +    {
 +      On3dPoint[] box_corners = new On3dPoint[8];​
 +      box_corners[0] = bbox.Corner(0,​0,​0);​
 +      box_corners[1] = bbox.Corner(1,​0,​0);​
 +      box_corners[2] = bbox.Corner(1,​1,​0);​
 +      box_corners[3] = bbox.Corner(0,​1,​0);​
 +      box_corners[4] = bbox.Corner(0,​0,​1);​
 +      box_corners[5] = bbox.Corner(1,​0,​1);​
 +      box_corners[6] = bbox.Corner(1,​1,​1);​
 +      box_corners[7] = bbox.Corner(0,​1,​1);​
 +
 +      On3dPoint[] rect = new On3dPoint[5];​
 +      OnLine line = new OnLine(); ;
 +      int box_type = ClassifyBBox(box_corners,​ ref rect, ref line); // returns 0=box, 1=rectangle,​ 2=line, 3=point
 +
 +      if (box_type == 3)
 +      {
 +        // BoundingBox failed. The bounding box is a point.
 +      }
 +      else if (box_type == 2)
 +      {
 +        // BoundingBox failed. The bounding box is a line.
 +      }
 +      else if (box_type == 1)
 +      {
 +        OnPolyline polyline = new OnPolyline();​
 +        polyline.Append(rect[0]);​
 +        polyline.Append(rect[1]);​
 +        polyline.Append(rect[2]);​
 +        polyline.Append(rect[3]);​
 +        polyline.Append(rect[4]);​
 +        context.m_doc.AddCurveObject(polyline);​
 +      }
 +      else // box_type == 0
 +      {
 +        OnBrep brep_box = OnUtil.ON_BrepBox(box_corners);​
 +        if (null != brep_box)
 +        {
 +          context.m_doc.AddBrepObject(brep_box);​
 +          num_added++;​
 +        }
 +      }
 +    }
 +  }
 +
 +  if (num_added > 0)
 +    context.m_doc.Redraw();​
 +
 +  return IRhinoCommand.result.success;​
 +}
 +
 +int ClassifyBBox(On3dPoint[] box_corners,​ ref On3dPoint[] rect, ref OnLine line)
 +{
 +  const double FLT_EPSILON = 1.192092896e-07F;​
 +  int numflat = 0;
 +  bool xflat = false, yflat = false, zflat = false;
 +
 +  if (FLT_EPSILON > box_corners[0].DistanceTo(box_corners[1]))
 +  {
 +    numflat++;
 +    xflat = true;
 +  }
 +
 +  if (FLT_EPSILON > box_corners[0].DistanceTo(box_corners[3]))
 +  {
 +    numflat++;
 +    yflat = true;
 +  }
 +
 +  if (FLT_EPSILON > box_corners[0].DistanceTo(box_corners[4]))
 +  {
 +    numflat++;
 +    zflat = true;
 +  }
 +
 +  if (numflat == 2)
 +  {
 +    line.from = box_corners[0];​
 +    if (!xflat)
 +      line.to = box_corners[1];​
 +    else if (!yflat)
 +      line.to = box_corners[3];​
 +    else
 +      line.to = box_corners[4];​
 +  }
 +  else if (numflat == 1)
 +  {
 +    rect[0] = rect[4] = box_corners[0];​
 +    if (xflat)
 +    {
 +      rect[1] = box_corners[4];​
 +      rect[2] = box_corners[7];​
 +      rect[3] = box_corners[3];​
 +    }
 +    else if (yflat)
 +    {
 +      rect[1] = box_corners[1];​
 +      rect[2] = box_corners[5];​
 +      rect[3] = box_corners[4];​
 +    }
 +    else // zflat
 +    {
 +      rect[1] = box_corners[1];​
 +      rect[2] = box_corners[2];​
 +      rect[3] = box_corners[3];​
 +    }
 +  }
 +
 +  return numflat;
 +}
 +</​code>​
 +
 +{{tag>​Developer dotnet}}
  
developer/sdksamples/tightboundingbox.txt ยท Last modified: 2015/09/14 (external edit)