Show Surface Direction
Demonstrates how to show a surface's direction using a display conduit.
partial class Examples
{
public static Rhino.Commands.Result ShowSurfaceDirection(Rhino.RhinoDoc doc)
{
Rhino.DocObjects.ObjRef objref;
var rc = Rhino.Input.RhinoGet.GetOneObject("Select surface or polysurface for direction display",
false,
Rhino.DocObjects.ObjectType.Surface | Rhino.DocObjects.ObjectType.PolysrfFilter,
out objref);
if (rc != Rhino.Commands.Result.Success)
return rc;
var brep = objref.Brep();
if (brep == null)
return Rhino.Commands.Result.Failure;
bool bIsSolid = brep.IsSolid;
TestSurfaceDirConduit conduit = new TestSurfaceDirConduit(brep);
conduit.Enabled = true;
doc.Views.Redraw();
var gf = new Rhino.Input.Custom.GetOption();
gf.SetCommandPrompt("Press enter when done");
gf.AcceptNothing(true);
if (!bIsSolid)
gf.AddOption("Flip");
for (; ; )
{
var res = gf.Get();
if (res == Rhino.Input.GetResult.Option)
{
conduit.Flip = !conduit.Flip;
doc.Views.Redraw();
continue;
}
if (res == Rhino.Input.GetResult.Nothing)
{
if (!bIsSolid && conduit.Flip)
{
brep.Flip();
doc.Objects.Replace(objref, brep);
}
}
break;
}
conduit.Enabled = false;
doc.Views.Redraw();
return Rhino.Commands.Result.Success;
}
}
class TestSurfaceDirConduit : Rhino.Display.DisplayConduit
{
readonly Brep m_brep;
readonly List<Point3d> m_points;
readonly List<Vector3d> m_normals;
public TestSurfaceDirConduit(Brep brep)
{
m_brep = brep;
Flip = false;
const int SURFACE_ARROW_COUNT = 5;
int face_count = m_brep.Faces.Count;
int capacity = face_count * SURFACE_ARROW_COUNT * SURFACE_ARROW_COUNT;
m_points = new List<Point3d>(capacity);
m_normals = new List<Vector3d>(capacity);
for (int i = 0; i < face_count; i++)
{
var face = brep.Faces[i];
var loop = face.OuterLoop;
if (loop == null)
continue;
var udomain = face.Domain(0);
var vdomain = face.Domain(1);
var loop_bbox = loop.GetBoundingBox(true);
if (loop_bbox.IsValid)
{
Interval domain = new Interval(loop_bbox.Min.X, loop_bbox.Max.X);
domain = Interval.FromIntersection(domain, udomain);
if (domain.IsIncreasing)
udomain = domain;
domain = new Interval(loop_bbox.Min.Y, loop_bbox.Max.Y);
domain = Interval.FromIntersection(domain, vdomain);
if (domain.IsIncreasing)
vdomain = domain;
}
bool bUntrimmed = face.IsSurface;
bool bRev = face.OrientationIsReversed;
for (double u = 0; u < SURFACE_ARROW_COUNT; u += 1.0)
{
double d = u / (SURFACE_ARROW_COUNT - 1.0);
double s = udomain.ParameterAt(d);
var intervals = face.TrimAwareIsoIntervals(1, s);
if (bUntrimmed || intervals.Length > 0)
{
for (double v = 0; v < SURFACE_ARROW_COUNT; v += 1.0)
{
d = v / (SURFACE_ARROW_COUNT - 1.0);
double t = vdomain.ParameterAt(d);
bool bAdd = bUntrimmed;
for (int k = 0; !bAdd && k < intervals.Length; k++)
{
if (intervals[k].IncludesParameter(t))
bAdd = true;
}
if (bAdd)
{
var pt = face.PointAt(s, t);
var vec = face.NormalAt(s, t);
m_points.Add(pt);
if (bRev)
vec.Reverse();
m_normals.Add(vec);
}
}
}
}
}
}
public bool Flip { get; set; }
protected override void DrawOverlay(Rhino.Display.DrawEventArgs e)
{
if (m_points.Count > 0)
{
var color = Rhino.ApplicationSettings.AppearanceSettings.TrackingColor;
for (int i = 0; i < m_points.Count; i++)
{
if (i % 100 == 0 && e.Display.InterruptDrawing())
break;
var pt = m_points[i];
var dir = m_normals[i];
if (Flip)
dir.Reverse();
e.Display.DrawDirectionArrow(pt, dir, color);
}
}
}
}
# No Python sample available
