Last active
February 28, 2017 14:49
-
-
Save goswinr/ab727d9b8d6ea619ec874641cff1786a to your computer and use it in GitHub Desktop.
A suggestion on how Rhinoscriptsyntax could be ported to F#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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