Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Based on the SDK Sampl GeometryCreation_BooleanOperations
- // This is testing code. Many improvements can be made before use in real work
- #r @"C:\Program Files\Autodesk\Revit 2016\RevitAPI.dll"
- #r @"C:\Program Files\Autodesk\Revit 2016\RevitDBAPI.dll"
- #r @"C:\Program Files\Autodesk\Revit 2016\RevitAPIUI.dll"
- #r @"C:\Program Files\Mantis\Tsunami.IDEDesktop.dll"
- open Autodesk.Revit
- open Autodesk.Revit.UI
- open System
- open System.Linq
- open System.Collections.Generic
- open Autodesk.Revit.DB
- open Autodesk.Revit.DB.Analysis
- open Autodesk.Revit.DB.Architecture
- open Autodesk.Revit.UI
- open Autodesk.Revit.UI.Selection
- open Autodesk.Revit.ApplicationServices
- open Autodesk.Revit.Attributes
- open System.Collections.Generic
- open System.Collections.Concurrent
- let memoize f =
- let cache = new ConcurrentDictionary<'a,'b>()
- fun x ->
- match cache.TryGetValue(x) with
- | (true,y) -> y
- | (false,_) ->
- let y = f x
- cache.[x] <- y
- y
- module Option =
- /// nullable
- let ofNullable (x : 'a) = if box x <> null then Some x else None
- /// System.Nullable
- let ofSystemNullable (x : System.Nullable<'a>) = if x.HasValue then Some x.Value else None
- let tryGetAll (xs:'a option []) =
- if xs |> Array.exists (function | None -> true | _ -> false)
- then None
- else xs |> Array.map (Option.get) |> Some
- let tryNull (x:'a) = if box x <> null then Some(x) else None
- let ofType<'Out> : obj -> 'Out option = function | :? 'Out as x -> Some x | _ -> None
- let tryNullOfType<'Out>(x:obj) : 'Out option = x |> tryNull |> ofType<'Out>
- let ofUnrelatedType<'In, 'Out> (x : 'In) = box x |> ofType<'Out>
- let isOfType<'a> (x:obj) = match x with | :? 'a -> true | _ -> false
- let orElse (second:'a option) (first:'a option) = match first with | Some(x) -> Some(x) | None -> match second with | Some(y) -> Some(y) | None -> None
- let tryFind (predicate:'a -> bool) (x:'a option) = match x with | Some(x) when predicate x -> Some(x) | _ -> None
- let orDefault (d:'a) (x:'a option) = match x with | Some(x) -> x | None -> d
- let ofRef (result:bool,byref:'a) = if result then Some(byref) else None
- module Seq =
- let ofType<'Out> = Seq.choose (Option.ofType<'Out>)
- let ofUnrelatedType<'In, 'Out> : 'In seq -> 'Out seq = Seq.choose (Option.ofUnrelatedType<'In, 'Out>)
- let tryLast (xs: 'a seq) = xs |> Seq.fold (fun _ x -> Some x) None
- let tryHead (xs:'a seq) =
- let ys = xs.GetEnumerator()
- if ys.MoveNext() then Some(ys.Current) else None
- module BooleanOperations =
- let inline (<||>) (s1:Solid) (s2:Solid) = BooleanOperationsUtils.ExecuteBooleanOperation(s1,s2,BooleanOperationsType.Union)
- let inline (<->) (s1:Solid) (s2:Solid) = BooleanOperationsUtils.ExecuteBooleanOperation(s1,s2,BooleanOperationsType.Difference)
- let inline (<&&>) (s1:Solid) (s2:Solid) = BooleanOperationsUtils.ExecuteBooleanOperation(s1,s2,BooleanOperationsType.Intersect)
- type CylinderDirection =
- | BasisX
- | BasisY
- | BasisZ
- let π = Math.PI
- let getViewByName(name:string) (doc:Document) =
- use xs = new FilteredElementCollector(doc)
- seq { for x in xs.OfClass(typeof<View>) -> x} |> Seq.ofUnrelatedType<Element,View> |> Seq.filter (fun x -> x.Name = name) |> Seq.tryHead
- let getView3DByName(name:string) (doc:Document) =
- use xs = new FilteredElementCollector(doc)
- seq { for x in xs.OfClass(typeof<View3D>) -> x} |> Seq.ofUnrelatedType<Element,View3D> |> Seq.filter (fun x -> x.Name = name) |> Seq.tryHead
- let get3DViewElementId(doc:Document) =
- use xs = new FilteredElementCollector(doc)
- seq { for x in xs.OfClass(typeof<ViewFamilyType>) -> x} |> Seq.ofUnrelatedType<Element,ViewFamilyType> |> Seq.filter (fun e -> e.Name = "3D View") |> Seq.tryHead |> Option.map (fun e -> e.Id)
- let create3DView =
- memoize (fun (name:string) (doc:Document) ->
- let view3DId = get3DViewElementId(doc).Value
- let view = View3D.CreateIsometric(doc, view3DId)
- let viewOrientation3D = new ViewOrientation3D(XYZ(1.,-1.,-1.), XYZ(1.,1.,1.), XYZ(1.,1.,-2.))
- view.SetOrientation(viewOrientation3D)
- view.SaveOrientation()
- view.Name <- name
- view)
- let createCenterBasedBox(center:XYZ, edgelength:float) =
- let halfedgelength = edgelength / 2.0
- let profileloops = List<CurveLoop>()
- let profileloop = new CurveLoop();
- [|
- (-1.,-1.,-1.), (-1., 1.,-1.)
- (-1., 1.,-1.), ( 1., 1.,-1.)
- ( 1., 1.,-1.), ( 1.,-1.,-1.)
- ( 1.,-1.,-1.), (-1.,-1.,-1.)
- |] |> Array.iter (fun ((a,b,c),(x,y,z)) ->
- let h = halfedgelength
- profileloop.Append(Line.CreateBound(XYZ(center.X + (h*a), center.Y + (h*b), center.Z + (h*c)),
- XYZ(center.X + (h*x), center.Y + (h*y), center.Z + (h*z)))))
- profileloops.Add(profileloop)
- let extrusiondir = XYZ.BasisZ
- GeometryCreationUtilities.CreateExtrusionGeometry(profileloops, extrusiondir, edgelength)
- let createCenterBasedSphere(center:XYZ, radius:float) =
- let frame = new Frame(center, XYZ.BasisX, XYZ.BasisY, XYZ.BasisZ)
- let profileloops = List<CurveLoop>()
- let profileloop = new CurveLoop()
- let cemiEllipse = Ellipse.Create(center, radius, radius, XYZ.BasisX, XYZ.BasisZ, -π / 2., π / 2.)
- profileloop.Append(cemiEllipse)
- profileloop.Append(Line.CreateBound(XYZ(center.X, center.Y, center.Z + radius), XYZ(center.X, center.Y, center.Z - radius)))
- profileloops.Add(profileloop)
- GeometryCreationUtilities.CreateRevolvedGeometry(frame, profileloops, -π, π)
- let createCenterBasedCylinder(center:XYZ, bottomradius:double, height:float, cylinderdirections:CylinderDirection) =
- let halfheight = height / 2.
- let bottomcenter,topcenter =
- match cylinderdirections with
- | BasisX -> XYZ(center.X - halfheight, center.Y, center.Z),XYZ(center.X + halfheight, center.Y, center.Z)
- | BasisY -> XYZ(center.X, center.Y - halfheight, center.Z),XYZ(center.X, center.Y + halfheight, center.Z)
- | BasisZ -> XYZ(center.X, center.Y, center.Z - halfheight),XYZ(center.X, center.Y, center.Z + halfheight)
- let sweepPath = new CurveLoop()
- sweepPath.Append(Line.CreateBound(bottomcenter, topcenter))
- let profileloops = List<CurveLoop>()
- let profileloop = new CurveLoop()
- let cemiEllipse1 =
- Ellipse.Create(bottomcenter, bottomradius, bottomradius,
- (if cylinderdirections = BasisX then XYZ.BasisY else XYZ.BasisX),
- (if cylinderdirections = BasisZ then XYZ.BasisY else XYZ.BasisZ),
- -π, 0.)
- let cemiEllipse2 =
- Ellipse.Create(bottomcenter, bottomradius, bottomradius,
- (if cylinderdirections = BasisX then XYZ.BasisY else XYZ.BasisX),
- (if cylinderdirections = BasisZ then XYZ.BasisY else XYZ.BasisZ),
- 0., π)
- profileloop.Append(cemiEllipse1)
- profileloop.Append(cemiEllipse2)
- profileloops.Add(profileloop)
- GeometryCreationUtilities.CreateSweptGeometry(sweepPath,0,0., profileloops)
- let mutable private schemaId = Option<int>.None
- let paintSolid(s:Solid, viewName:string, doc:Document) =
- let view = create3DView viewName doc
- let sfm =
- match SpatialFieldManager.GetSpatialFieldManager(view) |> Option.ofNullable with
- | Some(x) -> x
- | None -> SpatialFieldManager.CreateSpatialFieldManager(view,1)
- let getSchema() =
- let resultSchema1 = new AnalysisResultSchema("PaintedSolid" + viewName, "Description")
- let displayStyle = AnalysisDisplayStyle.CreateAnalysisDisplayStyle(doc, "Real_Color_Surface" + viewName,
- new AnalysisDisplayColoredSurfaceSettings(),
- new AnalysisDisplayColorSettings(),
- new AnalysisDisplayLegendSettings())
- resultSchema1.AnalysisDisplayStyleId <- displayStyle.Id
- sfm.RegisterResult(resultSchema1)
- let sId =
- match schemaId with
- | None ->
- let sId = getSchema()
- schemaId <- Some(sId)
- sId
- | Some(x) when not (sfm.GetRegisteredResults().Contains(x)) ->
- let sId = getSchema()
- schemaId <- Some(sId)
- sId
- | Some(x) -> x
- //sfm.GetRegisteredResults()
- for face in s.Faces do
- let idx = sfm.AddSpatialFieldPrimitive(face,Transform.Identity)
- let compteValueAtPointForFace(face:Face,measurementNo:int) : (UV[]*ValueAtPoint[]) =
- let bb = face.GetBoundingBox()
- [|
- for u in seq {bb.Min.U .. (bb.Max.U - bb.Min.U) .. bb.Max.U + 0.0000001 } do
- for v in seq {bb.Min.V .. (bb.Max.V - bb.Min.V) .. bb.Max.V + 0.0000001} do // Note original code devides by one which is weird
- let uvPnt = UV(u,v)
- let faceXYZ = face.Evaluate(uvPnt)
- let valPnt = new ValueAtPoint([|for ii = 1 to measurementNo do yield faceXYZ.DistanceTo(XYZ.Zero) * (float ii)|])
- yield (uvPnt,valPnt)
- |] |> fun xs -> (xs |> Array.map fst),(xs |> Array.map snd)
- let (uvPts,valList) = compteValueAtPointForFace(face,1)
- let pnts = new FieldDomainPointsByUV(uvPts)
- let vals = new FieldValues(valList)
- sfm.UpdateSpatialFieldPrimitive(idx,pnts, vals, sId)
- open BooleanOperations
- let zero = XYZ.Zero
- let xaxis = CylinderDirection.BasisX
- let yaxis = CylinderDirection.BasisY
- let zaxis = CylinderDirection.BasisZ
- let box(p,size) = createCenterBasedBox(p, size)
- let sphere(p,r) = createCenterBasedSphere(p, r)
- let cylinder(p,radius,length,direction) = createCenterBasedCylinder(p, radius, length, direction)
- let union y x = x <||> y
- let difference y x = x <-> y
- let intersect y x = x <&&> y
- let paint doc s = paintSolid(s, "CSGTree", doc)
- module Mantis =
- let transaction (f:Document->unit) =
- Mantis.run (fun app ->
- let document = app.ActiveUIDocument.Document
- let tran = new Transaction(document, "GeometryCreation_BooleanOperation");
- tran.Start() |> ignore
- f document
- tran.Commit() |> ignore
- )
- Mantis.transaction (fun doc ->
- sphere(zero,20.)
- |> intersect (box(zero,25.))
- |> difference
- ([
- cylinder(zero, 5., 40., xaxis)
- cylinder(zero, 5., 40., yaxis)
- cylinder(zero, 5., 40., zaxis)
- ] |> Seq.reduce union)
- |> paint doc
- )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement