usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingRhino;usingRhino.Commands;usingRhino.Geometry;usingRhino.Geometry.Intersect;usingRhino.Input;usingRhino.Input.Custom;usingRhino.DocObjects;namespace examples_cs
{publicclassFurthestZOnSurfaceCommand:Command{publicoverridestringEnglishName{get{return"csFurthestZOnSurfaceGivenXY";}}protectedoverrideResultRunCommand(RhinoDoc doc,RunMode mode){ #region user input// select a surfacevar gs =newGetObject();
gs.SetCommandPrompt("select surface");
gs.GeometryFilter=ObjectType.Surface;
gs.DisablePreSelect();
gs.SubObjectSelect=false;
gs.Get();if(gs.CommandResult()!=Result.Success)return gs.CommandResult();// get the brepvar brep = gs.Object(0).Brep();if(brep ==null)returnResult.Failure;// get X and Ydouble x =0.0, y =0.0;var rc =RhinoGet.GetNumber("value of X coordinate",true,ref x);if(rc !=Result.Success)return rc;
rc =RhinoGet.GetNumber("value of Y coordinate",true,ref y);if(rc !=Result.Success)return rc; #endregion// an earlier version of this sample used a curve-brep intersection to find Z//var maxZ = maxZIntersectionMethod(brep, x, y, doc.ModelAbsoluteTolerance);// projecting points is another way to find Zvar max_z =MaxZProjectionMethod(brep, x, y, doc.ModelAbsoluteTolerance);if(max_z !=null){RhinoApp.WriteLine("Maximum surface Z coordinate at X={0}, Y={1} is {2}", x, y, max_z);
doc.Objects.AddPoint(newPoint3d(x, y, max_z.Value));
doc.Views.Redraw();}elseRhinoApp.WriteLine("no maximum surface Z coordinate at X={0}, Y={1} found.", x, y);returnResult.Success;}privatestaticdouble?MaxZProjectionMethod(Brep brep,double x,double y,double tolerance){double? max_z =null;var breps =newList<Brep>{brep};var points =newList<Point3d>{newPoint3d(x, y,0)};// grab all the points projected in Z dir. Aggregate finds furthest Z from XY planetry{
max_z =(from pt inIntersection.ProjectPointsToBreps(breps, points,newVector3d(0,0,1), tolerance) select pt.Z)// Here you might be tempted to use .Max() to get the largest Z value but that doesn't work because// Z might be negative. This custom aggregate returns the max Z independant of the sign. If it had a name// it could be MaxAbs().Aggregate((z1, z2)=>Math.Abs(z1)>Math.Abs(z2)? z1 : z2);}catch(InvalidOperationException){/*Sequence contains no elements*/}return max_z;}privatedouble?MaxZIntersectionMethod(Brep brep,double x,double y,double tolerance){double? max_z =null;var bbox = brep.GetBoundingBox(true);var max_dist_from_xy =(from corner in bbox.GetCorners() select corner.Z)// furthest Z from XY plane.// Here you might be tempted to use .Max() to get the largest Z value but that doesn't work because// Z might be negative. This custom aggregate returns the max Z independant of the sign. If it had a name// it could be MaxAbs().Aggregate((z1, z2)=>Math.Abs(z1)>Math.Abs(z2)? z1 : z2);// multiply distance by 2 to make sure line intersects completelyvar line_curve =newLineCurve(newPoint3d(x, y,0),newPoint3d(x, y, max_dist_from_xy*2));Curve[] overlap_curves;Point3d[] inter_points;if(Intersection.CurveBrep(line_curve, brep, tolerance,out overlap_curves,out inter_points)){if(overlap_curves.Length>0|| inter_points.Length>0){// grab all the points resulting frem the intersection. // 1st set: points from overlapping curves, // 2nd set: points when there was no overlap// .Aggregate: furthest Z from XY plane.
max_z =(from c in overlap_curves select Math.Abs(c.PointAtEnd.Z)>Math.Abs(c.PointAtStart.Z)? c.PointAtEnd.Z: c.PointAtStart.Z).Union(from p in inter_points select p.Z)// Here you might be tempted to use .Max() to get the largest Z value but that doesn't work because// Z might be negative. This custom aggregate returns the max Z independant of the sign. If it had a name// it could be MaxAbs().Aggregate((z1, z2)=>Math.Abs(z1)>Math.Abs(z2)? z1 : z2);}}return max_z;}}}
import rhinoscriptsyntax as rs
fromRhino.GeometryimportIntersect,Point3d,Vector3dfrom scriptcontext import doc
defRunCommand():# select a surface
srfid = rs.GetObject("select serface", rs.filter.surface | rs.filter.polysurface)ifnot srfid:return# get the brep
brep = rs.coercebrep(srfid)ifnot brep:return
x = rs.GetReal("value of x",0)
y = rs.GetReal("value of y",0)
pts =[(abs(point.Z), point.Z)for point inIntersect.Intersection.ProjectPointsToBreps([brep],[Point3d(x, y,0)],Vector3d(0,0,1), doc.ModelAbsoluteTolerance)]
pts.sort(reverse=True)if pts ==[]:
print "no Z for given X, Y"else:
rs.AddPoint(Point3d(x, y, pts[0][1]))if __name__ =="__main__":RunCommand()
ImportsSystem.Collections.GenericImportsSystem.LinqImportsRhinoImportsRhino.CommandsImportsRhino.GeometryImportsRhino.Geometry.IntersectImportsRhino.InputImportsRhino.Input.CustomImportsRhino.DocObjectsNamespace examples_vb
PublicClassFurthestZOnSurfaceCommandInheritsCommandPublicOverridesReadOnlyPropertyEnglishName()AsStringGetReturn"vbFurthestZOnSurfaceGivenXY"EndGetEndPropertyProtectedOverridesFunctionRunCommand(doc AsRhinoDoc, mode AsRunMode)AsResult'#Region "user input"' select a surfaceDim gs =NewGetObject()
gs.SetCommandPrompt("select surface")
gs.GeometryFilter=ObjectType.Surface
gs.DisablePreSelect()
gs.SubObjectSelect=False
gs.[Get]()If gs.CommandResult()<>Result.SuccessThenReturn gs.CommandResult()EndIf' get the brepDim brep = gs.[Object](0).Brep()If brep IsNothingThenReturnResult.FailureEndIf' get X and YDim x AsDouble=0.0, y AsDouble=0.0Dim rc =RhinoGet.GetNumber("value of X coordinate",True, x)If rc <>Result.SuccessThenReturn rc
EndIf
rc =RhinoGet.GetNumber("value of Y coordinate",True, y)If rc <>Result.SuccessThenReturn rc
EndIf'#End Region' an earlier version of this sample used a curve-brep intersection to find Z'var maxZ = MaxZIntersectionMethod(brep, x, y, doc.ModelAbsoluteTolerance);' projecting points is another way to find ZDim maxZ =MaxZProjectionMethod(brep, x, y, doc.ModelAbsoluteTolerance)If maxZ IsNotNothingThenRhinoApp.WriteLine("Maximum surface Z coordinate at X={0}, Y={1} is {2}", x, y, maxZ)
doc.Objects.AddPoint(NewPoint3d(x, y, maxZ.Value))
doc.Views.Redraw()ElseRhinoApp.WriteLine("no maximum surface Z coordinate at X={0}, Y={1} found.", x, y)EndIfReturnResult.SuccessEndFunctionPrivateFunctionMaxZProjectionMethod(brep AsBrep, x AsDouble, y AsDouble, tolerance AsDouble)AsSystem.Nullable(OfDouble)Dim maxZ AsSystem.Nullable(OfDouble)=NothingDim breps =NewList(OfBrep)()From{ _
brep _
}Dim points =NewList(OfPoint3d)()From{ _
NewPoint3d(x, y,0) _
}' grab all the points projected in Z dir. Aggregate finds furthest Z from XY planeTry
maxZ =(From pt InIntersection.ProjectPointsToBreps(breps, points,NewVector3d(0,0,1), tolerance)Select pt.Z).Aggregate(Function(z1, z2)If(Math.Abs(z1)>Math.Abs(z2), z1, z2))'Sequence contains no elementsCatch generatedExceptionName AsInvalidOperationExceptionEndTryReturn maxZ
EndFunctionPrivateFunctionMaxZIntersectionMethod(brep AsBrep, x AsDouble, y AsDouble, tolerance AsDouble)AsSystem.Nullable(OfDouble)Dim maxZ AsSystem.Nullable(OfDouble)=NothingDim bbox = brep.GetBoundingBox(True)' furthest Z from XY plane. Max() doesn't work because of possible negative Z valuesDim maxDistFromXY =(From corner In bbox.GetCorners()Select corner.Z).Aggregate(Function(z1, z2)If(Math.Abs(z1)>Math.Abs(z2), z1, z2))' multiply distance by 2 to make sure line intersects completelyDim lineCurve =NewLineCurve(NewPoint3d(x, y,0),NewPoint3d(x, y, maxDistFromXY *2))Dim overlapCurves AsCurve()=NothingDim interPoints AsPoint3d()=NothingIfIntersection.CurveBrep(lineCurve, brep, tolerance, overlapCurves, interPoints)ThenIf overlapCurves.Length>0OrElse interPoints.Length>0Then' grab all the points resulting frem the intersection. ' 1st set: points from overlapping curves, ' 2nd set: points when there was no overlap' .Aggregate: furthest Z from XY plane.Dim overlapCrvsZs AsIEnumerable(OfDouble)=(From c In overlapCurves SelectDirectCast(IIf(Math.Abs(c.PointAtEnd.Z)>Math.Abs(c.PointAtStart.Z), c.PointAtEnd.Z, c.PointAtStart.Z),Double))Dim intersectPtsZs AsIEnumerable(OfDouble)=(From p In interPoints Select p.Z)Dim allZs = overlapCrvsZs.Union(intersectPtsZs).ToArray()
maxZ = allZs.Aggregate(Function(runZ, nextZ)DirectCast(IIf(Math.Abs(runZ)>Math.Abs(nextZ), runZ, nextZ),Double))EndIfEndIfReturn maxZ
EndFunctionEndClassEndNamespace