Skip to content

Instantly share code, notes, and snippets.

@goswinr
Last active February 28, 2017 14:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save goswinr/ab727d9b8d6ea619ec874641cff1786a to your computer and use it in GitHub Desktop.
Save goswinr/ab727d9b8d6ea619ec874641cff1786a to your computer and use it in GitHub Desktop.
A suggestion on how Rhinoscriptsyntax could be ported to F#
open Microsoft.FSharp.Collections
open FsEx // some F# helper libraries. eg.type Rarr = ResizeArray
open System
open Rhino
open Rhino.Geometry
open System.Drawing
module GeoExchange =
// translation from custom 3D classes
let inline rhPt (p:Geo.Pnt) = Point3d(p.x,p.y,p.z)
let inline rhVe (p:Geo.Vec) = Vector3d(p.x,p.y,p.z)
let inline rhLn (l:Geo.Line) = Line(rhPt l.a, rhPt l.b)
///* import like this: module rs = FsEx.RhinoScriptSyntax
module RhinoScriptSyntax =
open GeoExchange
let isRh = Rhino.Runtime.HostUtils.RunningInRhino
let mutable ArialNarrowIndex = -1
let mutable ISOCPIndex = -1
let mutable Doc = if isRh then Rhino.RhinoDoc.ActiveDoc else null
let mutable Ot = if isRh then Rhino.RhinoDoc.ActiveDoc.Objects else null
type RhApp = Rhino.RhinoApp// type alias
let private updateDoc (args:Rhino.DocumentOpenEventArgs) =
Doc <- args.Document
Ot <- args.Document.Objects
if isRh then
Rhino.RhinoDoc.EndOpenDocument.Add updateDoc // to udate documnet reference
RhApp.EscapeKeyPressed.Add ( fun _ -> failwith "Esc Key was pressed and cought via F# Dll")
ArialNarrowIndex <- Doc.Fonts.FindOrCreate("Arial Narrow",false,false) |>> ( fun i -> if i <0 then failwith "***Arial Narrow Font not found")
ISOCPIndex <- Doc.Fonts.FindOrCreate("ISOCP",false,false) |>> ( fun i -> if i <0 then failwith "***ISOCP font not found")
(* let doAsync f arg =
async{ do! Async.SwitchToContext Tsunami.IDE.HostThread.syncContext.Value
return f arg}
|> Async.RunSynchronously // done in extra project *)
///*prints generic objects to the commandline
let print ob = if isRh then RhApp.WriteLine <| str ob ; RhApp.Wait() else System.Console.WriteLine (str ob)
let print2 ob1 ob2 = if isRh then RhApp.WriteLine <| str ob1+" "+str ob2 ; RhApp.Wait() else System.Console.WriteLine (str ob1+" "+str ob2 )
let print3 ob1 ob2 ob3 = let txt = str ob1+" "+str ob2+" "+str ob3 in if isRh then RhApp.WriteLine txt ; RhApp.Wait() else System.Console.WriteLine txt
let print4 ob1 ob2 ob3 ob4 = let txt = str ob1+" "+str ob2+" "+str ob3+" "+str ob4 in if isRh then RhApp.WriteLine txt ; RhApp.Wait() else System.Console.WriteLine txt
///* sets text in command prompt by generic objects to the commandline
let prompt txt = RhApp.SetCommandPrompt txt ; RhApp.Wait()
let inline redraw () = Doc.Views.Redraw () ; RhApp.Wait()
let inline redrawIgnore _ = Doc.Views.Redraw () ; RhApp.Wait()
let inline statusBarMsg txt = UI.StatusBar.SetMessagePane txt ; RhApp.Wait()
let coerceRhinoObject (guid:Guid) = guid |>> checkNonNull "coerceRhinoObject1" |> Ot.Find |>> checkNonNull "coerceRhinoObject2"
let coerceGeometry (guid:Guid) = (coerceRhinoObject guid).Geometry
let coerceCurve (guid:Guid) =
match coerceGeometry guid with
| :? Curve as c -> c
| _ -> failwithf "*** Coerce Curve failed"
let coerceRhinoPoint3d (pt:'PtObj) =
match box pt with
| :? Point3d as pt -> pt
| :? Geo.Pnt as p -> rhPt p
| :? Vector3d as v -> Point3d(v)
| :? Point3f as pt -> Point3d(pt)
| :? (float*float*float) as xyz -> let x,y,z = xyz in Point3d(x,y,z)
| :? System.Guid as g ->
if Guid.Empty = g then failwithf "*** could not coerce %A to Point3d" pt
match (g |> Ot.Find|>> checkNonNull "Find GUID in coerceRhinoPoint3d").Geometry with
| :? Rhino.Geometry.Point as geom -> geom.Location
| _ -> failwithf "*** could not coerce %A to Point3d" pt
| _ -> failwithf "*** could not coerce %A to Point3d" pt
let coerceRhinoPlane (pl:'PlOrPt) =
match box pl with
| :? Plane as pl -> pl
| :? Geo.Plane as pl -> Plane(rhPt pl.Pt, rhVe pl.N)
| :? Geo.PPlane as pl -> Plane(rhPt pl.Pt, rhVe pl.Xax,rhVe pl.Yax )
| :? Point3d as pt -> Plane(pt , Vector3d(1.,0.,0.), Vector3d(0.,1.,0.))
| :? Geo.Pnt as v -> Plane(rhPt v, Vector3d(1.,0.,0.), Vector3d(0.,1.,0.))
| x -> failwithf "*** could not convert %A to Rhino Plane" x
let allObjects () =
let it = Rhino.DocObjects.ObjectEnumeratorSettings()
it.IncludeLights <- false
it.IncludeGrips <- false
it.NormalObjects <- true
it.LockedObjects <- true
it.HiddenObjects <- true
it.ReferenceObjects <- false
Ot.GetObjectList it
|> Seq.map ( fun o -> o.Id)
///*Adds a new layer ,returns index, even if Layer already exists
let addLayer name =
if name = "" then failwith "Layername cannot be empty string"
let mutable i = Doc.Layers.FindByFullPath (name,true)
if i < 0 then i <- Doc.Layers.Find (name,true)
if i >= 0 then i
else
let l = DocObjects.Layer.GetDefaultLayerProperties(Name = name, Color = Color.randomColorForRhino() )
l.PlotColor <- Color.Black ; l.CommitChanges()|> ignore
Doc.Layers.Add l
///*Adds a new layer and parent Layer ,returns index, even if Layer already exists
let addLayerPar parentName name =
let iParent = addLayer parentName
let parent = Doc.Layers.[iParent]
let layer = DocObjects.Layer.GetDefaultLayerProperties(Name = name, Color = Color.randomColorForRhino(), ParentLayerId = parent.Id)
layer.PlotColor <- Color.Black;layer.CommitChanges()|> ignore
let mutable i = Doc.Layers.Add layer
if i<0 then i <- Doc.Layers.FindByFullPath (parentName+"::"+name,true)
if i<0 then i <- Doc.Layers.Find (name,true)
i
///*Adds a new layer, parent Layer and parent parent Layer ,returns index, even if Layer already exists
let addLayerParPar parentParentName parentName name =
let iPParent = addLayer parentParentName
let pParent = Doc.Layers.[iPParent]
let parent = DocObjects.Layer.GetDefaultLayerProperties(Name = parentName, Color = Color.randomColorForRhino(), ParentLayerId = pParent.Id)
parent.PlotColor <- Color.Black;parent.CommitChanges()|> ignore
let mutable ip = Doc.Layers.Add parent
if ip<0 then ip <- Doc.Layers.FindByFullPath (parentParentName+"::"+parentName,true)
if ip<0 then ip <- Doc.Layers.Find (parentName,true)
let parent = Doc.Layers.[ip]
let layer = DocObjects.Layer.GetDefaultLayerProperties(Name = name, Color = Color.randomColorForRhino(), ParentLayerId = parent.Id)
layer.PlotColor <- Color.Black;layer.CommitChanges()|> ignore
let mutable i = Doc.Layers.Add layer
if i<0 then i <- Doc.Layers.FindByFullPath (parentParentName+"::"+parentName+"::"+name,true)
if i<0 then i <- Doc.Layers.Find (name,true)
i
let addLine (a:Geo.Pnt) (b:Geo.Pnt) = if not (a-b).IsZero then Ot.AddLine(rhPt a, rhPt b) else failwithf "Cannot Draw Zero Line from %A to %A" a b
let addLineIgnore (a:Geo.Pnt) (b:Geo.Pnt) = addLine a b |> ignore
let addLineObj (ln:Geo.Line) = if not ln.IsZeroLength then Ot.AddLine (rhLn ln) else failwithf "Cannot Draw Zero: %A" ln
let addPoint pt = pt |> coerceRhinoPoint3d |> Ot.AddPoint
let addPointIgnore pt = pt |> coerceRhinoPoint3d |> Ot.AddPoint |> ignore
let addPolyline (pts: seq<'Pt>) =
let ps = pts |> Rarr.ofSeq |> Rarr.map coerceRhinoPoint3d
if ps.Count < 2 then failwithf "*** addPolyline from 1 or 0 elements: %A" pts
Ot.AddPolyline ps |>> checkNonNull2 "addPolyline" pts
///* closed Polyline from not closed Seq
let addClosedPolyline (pts: seq<'Pt>) =
let ps = pts |> Rarr.ofSeq |> Rarr.map coerceRhinoPoint3d
if ps.Count < 2 then failwithf "*** addClosedPolyline from 1 or 0 elements: %A" pts
ps.Add ps.[0]
Ot.AddPolyline ps |>> checkNonNull2 "addClosedPolyline" pts
///*adds points in list
let addPts (pts: seq<'Pt>) =
if Seq.isEmpty pts then failwith "* addPts: Seq empty"
let gs = Rarr<System.Guid>()
for p in pts do
gs.Add <| (p |> coerceRhinoPoint3d |> Ot.AddPoint)
gs
///*adds points in list of list of points
let addPtsNested (ptss: seq<seq<'Pt>>) =
if Seq.isEmpty ptss then failwith "* addPtsNested: Seq empty"
let gs = Rarr<System.Guid>()
for pts in ptss do
gs.AddRange <| addPts pts
gs
let addTextDot (txt:string) (pt:'Pt) = Ot.AddTextDot (txt |>> checkStr "addTextDot", coerceRhinoPoint3d pt)
//let addTextDot (txt:string) (pt: Geo.Pnt) = Ot.AddTextDot (txt |>> checkStr "addTextDot" , pt.RhPt)
let addTextDotIgnore (txt:string) (pt:'Pt) = Ot.AddTextDot (txt |>> checkStr "addTextDotIgnore" , coerceRhinoPoint3d pt) |> ignore
let addTextMid mask (h:float) (txt:string) (pl:'PlOrPt) =
let txtE = new TextEntity ()
txtE.Text <- txt |>> checkStr "addText"
txtE.TextHeight <- h
txtE.Plane <- coerceRhinoPlane pl
txtE.FontIndex <- ArialNarrowIndex
txtE.Justification <- TextJustification.MiddleCenter
if mask then
txtE.MaskEnabled <- true
txtE.MaskColor <- Drawing.Color.White
txtE.MaskOffset <- 0.1
Ot.AddText(txtE)
let addTextLeft mask (h:float) (txt:string) (pl:'PlOrPt) =
let txtE = new TextEntity ()
txtE.Text <- txt |>> checkStr "addText"
txtE.TextHeight <- h
txtE.Plane <- coerceRhinoPlane pl
txtE.FontIndex <- ArialNarrowIndex // ISOCPIndex
txtE.Justification <- TextJustification.MiddleLeft
if mask then
txtE.MaskEnabled <- true
txtE.MaskColor <- Drawing.Color.White
//txtE.MaskUsesViewportColor <- true
txtE.MaskOffset <- 0.1
Ot.AddText(txtE)
///* Add rectangle centered om plane origin
let addRectCen l h (pl:Geo.PPlane) =
let l' = l*0.5
let h' = h*0.5
let a = pl.AtXY ( l', h') |> rhPt
let b = pl.AtXY (-l', h') |> rhPt
let c = pl.AtXY (-l', -h') |> rhPt
let d = pl.AtXY ( l', -h') |> rhPt
Ot.AddPolyline [|a;b;c;d;a|] |>> checkNonNull3 "rs.addRectCen" l h
///* Add triangle centered om plane origin, give circumference radius
let addTriaCen rad (pl:Geo.PPlane) =
let l = 30. |> Math.degToRad |> sin |> ( * ) rad
let h = 30. |> Math.degToRad |> cos |> ( * ) rad
let a = pl.AtXY ( rad, 0.) |> rhPt
let b = pl.AtXY ( -l , -h ) |> rhPt
let c = pl.AtXY ( -l , h ) |> rhPt
Ot.AddPolyline [|a;b;c;a|] |>> checkNonNull2 "rs.addTriaCen" rad
let command txt = RhApp.RunScript (txt,false) |> ignore
let currentViewGet () = Doc.Views.ActiveView.ActiveViewport.Name
let currentViewSet txt =
let v = Doc.Views.Find (txt,false)
if isNull v then failwithf "*** cannotSet view '%s'" txt
Doc.Views.ActiveView <- v
let curveArrows s e crvg =
let crvo = coerceRhinoObject crvg
let attr = crvo.Attributes
match s,e with
|false,false -> attr.ObjectDecoration <- DocObjects.ObjectDecoration.None
|true ,false -> attr.ObjectDecoration <- DocObjects.ObjectDecoration.StartArrowhead
|false,true -> attr.ObjectDecoration <- DocObjects.ObjectDecoration.EndArrowhead
|true ,true -> attr.ObjectDecoration <- DocObjects.ObjectDecoration.BothArrowhead
Ot.ModifyAttributes(crvo, attr, false) |> ignore
crvg
let curveLength g =
let c = coerceCurve g
c.GetLength()
let drawPlane (sc:float) pl =
let p = coerceRhinoPlane pl
[| yield Ot.AddLine( p.Origin, (p.Origin+p.XAxis*sc))
yield Ot.AddLine( p.Origin, (p.Origin+p.YAxis*sc*0.5))
yield Ot.AddLine( p.Origin, (p.Origin+p.ZAxis*sc*0.2)) |]
let deleteObjects (gs: Guid seq) = if not <| Seq.isEmpty gs then Doc.Objects.Delete (gs,false) |> ignore
let hideObjects (gs: Guid seq) = if not <| Seq.isEmpty gs then for g in gs do Doc.Objects.Hide (g,false) |> ignore
let showObjects (gs: Guid seq) = if not <| Seq.isEmpty gs then for g in gs do Doc.Objects.Show (g,false) |> ignore
let isLayer (name:string) = Doc.Layers.Find (name,true) >= 0
///*retuns true if Layer exists. give FullPath like: "parent::parent::child"
let isLayerFull name = Doc.Layers.FindByFullPath (name,true) >= 0
let isPoint g =
if Guid.Empty = g then failwith "*** rs.isPoint faild on Empty GUID"
match (g |> Ot.Find |>> checkNonNull "Find GUID in isPoint" ).Geometry with
| :? Rhino.Geometry.Point -> true
| _ -> false
let isCurve g =
if Guid.Empty = g then failwith "*** rs.isCurve faild on Empty GUID"
match (g |> Ot.Find |>> checkNonNull "Find GUID in isCurve" ).Geometry with
| :? Rhino.Geometry.Curve -> true
| _ -> false
let isMesh g =
if Guid.Empty = g then failwith "*** rs.isCurve faild on Empty GUID"
match (g |> Ot.Find |>> checkNonNull "Find GUID in isCurve" ).Geometry with
| :? Rhino.Geometry.Mesh -> true
| _ -> false
let getObject txt =
// this is needs to be async for Tsunami
use getter = new Rhino.Input.Custom.GetObject()
getter.SetCommandPrompt (if txt = "" then "Select one Object" else txt)
getter.AcceptNothing true
getter.GroupSelect <- false
getter.GeometryFilter <- Rhino.DocObjects.ObjectType.AnyObject
let res = getter.Get()
if res = Rhino.Input.GetResult.Object
then Some((getter.Object 0).ObjectId)
else None
let getObjects txt =
// this is needs to be async for Tsunami
use getter = new Rhino.Input.Custom.GetObject()
getter.SetCommandPrompt (if txt = "" then "Select multiple Objects" else txt)
getter.AcceptNothing true
getter.GroupSelect <- false
getter.GeometryFilter <- Rhino.DocObjects.ObjectType.AnyObject
let res = getter.GetMultiple(1,0)
if res = Rhino.Input.GetResult.Object && getter.ObjectCount > 0
then Rarr.init getter.ObjectCount (fun i -> (getter.Object i).ObjectId)
else print "*** No Objects selected."; Rarr()
let layerVisible visible (layer:string) =
let i = Doc.Layers.Find (layer,true)
if i<0 then failwithf "*** layer '%s' not found" layer
let lay = Doc.Layers.[i]
lay.IsVisible <- visible
lay.CommitChanges()|> ignore
Doc.Views.Redraw()
let objectLayerIndex guid = guid |>> checkNonNull "objectLayerIndex" |> coerceRhinoObject |> fun o -> o.Attributes.LayerIndex
let objectLayerIndexSet index guid =
let o = guid |>> checkNonNull "objectLayerIndexSet" |> coerceRhinoObject
o.Attributes.LayerIndex <- index
o.CommitChanges () |> ignore
guid
let objectLayer guid = guid |>> checkNonNull "objectLayer get" |> coerceRhinoObject |> fun o -> Doc.Layers.[o.Attributes.LayerIndex].Name
///*sets the layer of an object, creats new layer if layer does not exist yet, give Name as String, returns guid for piping
let objectLayerSet name guid = guid |>> checkNonNull2 name "objectLayerSet" |> objectLayerIndexSet (addLayer name)
let objectsLayerSet name guids = guids |>> checkNonNull2 name "objectsLayerSet" |> Seq.map (objectLayerIndexSet (addLayer name))
///*sets the layer of an object, creats new layer if layer does not exist yet, give first ParentName then Name as String, returns guid for piping
let objectLayerSetPar parentName name guid =
let i = addLayerPar parentName name
guid |>> checkNonNull3 parentName name "objectLayerSetPar" |> objectLayerIndexSet i
///*sets the layer of an object, creats new layer if layer does not exist yet, give first ParentName and Parent Parent Name then Name as String, returns guid for piping
let objectLayerSetParPar parentParentName parentName name guid =
let i = addLayerParPar parentParentName parentName name
guid |>> checkNonNull3 parentName name "objectLayerSetParPar" |> objectLayerIndexSet i
///*returns full Path of object LayerName, Parent::Parent::Child
let objectLayerFull guid = guid |> coerceRhinoObject |> fun o -> Doc.Layers.[o.Attributes.LayerIndex].FullPath
let objectName guid = (guid |> coerceRhinoObject).Name
let objectNameSet name guid =
//if isNull guid then guid // remove this bypass !!!!!!!!!!!!!!!!!
//else
let o = guid |> coerceRhinoObject
let attr = o.Attributes
attr.Name <- name
o.CommitChanges () |> ignore
guid
let objectsByName name =
// https://github.com/mcneel/rhinopython/blob/master/scripts/rhinoscript/selection.py
let mutable settings = DocObjects.ObjectEnumeratorSettings()
settings.HiddenObjects <- true
settings.DeletedObjects <- false
settings.IncludeGrips <- false
settings.IncludePhantoms <- true
settings.IncludeLights <- false
settings.NameFilter <- name
settings.ReferenceObjects <- false
let objects = Doc.Objects.GetObjectList settings
[|for rhobj in objects do yield rhobj.Id|]
let textObjectText text (g:Guid) =
let annotation = coerceGeometry g :?> Geometry.TextEntity
annotation.Text <- text
Doc.Objects.Replace(g, annotation) |> ignore
let setUserText key txt guid = if (guid |> coerceRhinoObject).Attributes.SetUserString(key,txt) then guid else failwithf "*** setUserText on '%s', '%s', '%A' failed" key txt guid
let getUserText key guid = (guid |> coerceRhinoObject).Attributes.GetUserString key
let getUserTextKeys guid = ((guid |> coerceRhinoObject).Attributes.GetUserStrings ()).AllKeys
///* modifies mesh in Place
let meshUnWeld ang (m:Mesh) = m.Unweld(ang,true) ; m
///* modifies mesh in Place
let meshWeld ang (m:Mesh) = m.Weld ang ; m
///* make sure last and first Points are not the same
let meshFromConvexPts (pts:Geo.Pnt []) =
let m = new Mesh()
let l = pts.Length
if l < 3 then failwithf " cannot add mesh face from %d Points %A" pts.Length pts
elif l = 4 then m.addQuadFace (pts.[0], pts.[1], pts.[2], pts.[3])
elif l = 3 then m.addTriaFace (pts.[0], pts.[1], pts.[2])
else
// add first face
let il = pts.LastIndex
let s0 = pts.[0]
let e0 = pts.[il]
let s1 = pts.[1]
let e1 = pts.[il-1]
let mutable a = m.Vertices.Add (s0.x,s0.y,s0.z)
let mutable b = m.Vertices.Add (e0.x,e0.y,e0.z)
let mutable c = m.Vertices.Add (e1.x,e1.y,e1.z)
let mutable d = m.Vertices.Add (s1.x,s1.y,s1.z)
m.Faces.AddFace(a,b,c,d) |> ignore
for i=2 to ((l+1) / 2) - 1 do // to do half of them and finish with tria on odd pointcount
let s = pts.[i]
let e = pts.[il-i]
a <- d
b <- c
c <- m.Vertices.Add (e.x,e.y,e.z)
if i <> il-i then
d <- m.Vertices.Add (s.x,s.y,s.z)
m.Faces.AddFace(a,b,c,d) |> ignore
else
m.Faces.AddFace(a,b,c) |> ignore
m
///* returns new curve with location of new controll points, same weights and knot vectors
let crvUpdateControlPoints (pts: Point3d seq) (crv: NurbsCurve) =
if Seq.length pts <> crv.Points.Count then
failwithf "*** crvUpdateControlPoints Length mismatch %d points vs %d controlpoints in Crv" (Seq.length pts) crv.Points.Count
let c = new Geometry.NurbsCurve(crv)
for i,pt in Seq.enumerate pts do
let mutable cp = Geometry.ControlPoint()
cp.Location <- pt
cp.Weight <- c.Points.[i].Weight
c.Points.[i] <- cp
c
///* Boolean Substraction, tolerance = 0.05, brepsTOSubtract:seq -> brepToSubtractFrom -> brepResult
let private brepSubtractMain blraise gcollect (subs:Brep Rarr) (b:Brep) =
if subs.Count = 0 then b
else
let mutable tol = 0.05 // 0.001
let mutable rb = null
(* while isNull rb && tol < 101. do // try various Tolerances
tol <- tol * 5.
rb <- Geometry.Brep.CreateBooleanDifference ([b], subs, tol) *)
rb <- Geometry.Brep.CreateBooleanDifference ([b], subs, tol)
if isNull rb then
print4 "*** brepSubtract failed for " subs.Count " at Tolerance " tol // from Tolerance 0.005 up to" tol
subs |> Rarr.iter (Ot.AddBrep >> objectLayerSet "failedCutWith" >> ignore )
b |> Ot.AddBrep |> objectLayerSet "failedCutFrom" |> ignore
b
elif rb.Length = 1 then
if gcollect then subs |> Seq.iter dispose // Dispose ??
//rb.[0].Standardize()
//rb.[0].Compact()
rb.[0]
elif rb.Length = 0 then
if blraise then
print4 "*** brepSubtract failed with 0 breps in result for " subs.Count " with Tolerance " tol
subs |> Rarr.iter (Ot.AddBrep >> objectLayerSet "zeroResult-with-these" >> ignore )
b |> Ot.AddBrep |> objectLayerSet "zeroResult-from-this" |> ignore
b
else
print6 "*** brepSubtract failed with" rb.Length " breps in results for " subs.Count "with Tolerance" tol
rb |> Array.iter (Ot.AddBrep >> objectLayerSet "tooManyBreps" >> ignore)
rb.[0]
///* if no intersection found also reports and draws it, still returns original brep
let brepSubtract (subs:Brep Rarr) (b:Brep) = brepSubtractMain true true subs b
///* returns original berp if no intersection found
let brepTrySubtract (subs:Brep Rarr) (b:Brep) = brepSubtractMain false false subs b
///* creates exactly one planar Brep from Curves
let brepPlanarFromCrvs (crvs:seq<Curve>) =
let rb = Geometry.Brep.CreatePlanarBreps(crvs)
if isNull rb then
for crv in crvs do
addTextDot "Planar srf failed" crv.PointAtStart |> ignore
let v,log = crv.IsValidWithLog()
if not v then failwithf "*** failed to make planar Brep from %A, invalid crv: %s" crvs log
else crv |> Ot.AddCurve |> ignore
failwithf "*** failed to make planar Brep from %A at tolerance %f" crvs Doc.ModelAbsoluteTolerance
elif rb.Length <> 1 then
rb |> Seq.iter (Ot.AddBrep >> ignore)
failwithf "*** %d planar Breps from Curves: %A instead of just one, at tolerance %f" rb.Length crvs Doc.ModelAbsoluteTolerance
else
rb.[0]
///* joins Breps ,disposes input, with Tolerance 0.1 to one Brep
let brepsJoin breps =
//let rb = Geometry.Brep.CreateSolid (breps |> Rarr.toArray, 0.05) //does not wor on P profiles
let tol = 0.1
let rb = Geometry.Brep.JoinBreps (breps , tol)
if isNull rb then
breps |> Seq.iter (Ot.AddBrep >> ignore)
failwithf "* failed to join Breps %A at special tolerance %f" breps tol
elif rb.Length <> 1 then
rb |> Seq.iter (Ot.AddBrep >> ignore)
failwithf "%d breps from join Breps command %A at special tolerance %f" rb.Length breps tol
else
breps |> Seq.iter dispose
rb.[0] // return Brep
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment