Skip to content

Commit

Permalink
Merge pull request #1171 from mcneel/1.24
Browse files Browse the repository at this point in the history
Implemented `Types.ScopeBox.BakeElement`.
  • Loading branch information
kike-garbo authored Aug 23, 2024
2 parents 5208e2f + 6153ca5 commit 940ed0e
Showing 1 changed file with 238 additions and 1 deletion.
239 changes: 238 additions & 1 deletion src/RhinoInside.Revit.GH/Types/Views/ScopeBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using System.Linq;
using Grasshopper.Kernel;
using Rhino.Geometry;
using Rhino.DocObjects;
using Rhino;
using ERDB = RhinoInside.Revit.External.DB;
using ARDB = Autodesk.Revit.DB;

Expand All @@ -15,7 +17,7 @@ namespace RhinoInside.Revit.GH.Types
using ARDB_ScopeBox = ARDB.Element;

[Kernel.Attributes.Name("Scope Box")]
public class ScopeBox : GraphicalElement
public class ScopeBox : GraphicalElement, Bake.IGH_BakeAwareElement
{
protected override Type ValueType => typeof(ARDB_ScopeBox);
public new ARDB_ScopeBox Value => base.Value as ARDB_ScopeBox;
Expand Down Expand Up @@ -137,5 +139,240 @@ public override Plane Location
}
}
#endregion

#region IGH_BakeAwareElement
bool IGH_BakeAwareData.BakeGeometry(RhinoDoc doc, ObjectAttributes att, out Guid guid) =>
BakeElement(new Dictionary<ARDB.ElementId, Guid>(), true, doc, att, out guid);

public bool BakeElement
(
IDictionary<ARDB.ElementId, Guid> idMap,
bool overwrite,
RhinoDoc doc,
ObjectAttributes att,
out Guid guid
)
{
// 1. Check if is already cloned
if (idMap.TryGetValue(Id, out guid))
return true;

if (Value is ARDB_ScopeBox)
{
att = att?.Duplicate() ?? doc.CreateDefaultAttributes();
att.Name = DisplayName;
if (Category.BakeElement(idMap, false, doc, att, out var layerGuid))
att.LayerIndex = doc.Layers.FindId(layerGuid).Index;

// 2. Check if already exist
var index = doc.Groups.Find(att.Name);
if (index >= 0) guid = doc.Groups.FindIndex(index).Id;

// 3. Update if necessary
if (index < 0 || overwrite)
{
if (index < 0) index = doc.Groups.Add(att.Name);
if (overwrite && index >= 0)
{
var objects = doc.Objects.FindByGroup(index);
var viewportIds = new Dictionary<int, HashSet<Guid>>();
foreach (var obj in objects)
{
if (obj is ClippingPlaneObject clipper)
viewportIds[viewportIds.Count] = new HashSet<Guid>(clipper.ClippingPlaneGeometry.ViewportIds());

doc.Objects.Delete(obj, quiet: true, ignoreModes: true);
}

var box = Box;

// Instance
if
(
BakeInstanceDefinition(idMap, overwrite, doc, att, out var idef_id) &&
doc.InstanceDefinitions.FindId(idef_id) is InstanceDefinition idef
)
{
using (var instanceAtt = att.Duplicate())
{
var xform = Transform.PlaneToPlane(Plane.WorldXY, box.Plane) *
Transform.Scale(Plane.WorldXY, box.X.Length, box.Y.Length, box.Z.Length);

instanceAtt.AddToGroup(index);
guid = doc.Objects.AddInstanceObject(idef.Index, xform, instanceAtt);
}
}

// Clipping Planes
if (guid != Guid.Empty)
{
using (var planesAtt = att.Duplicate())
{
var parent = doc.Layers[att.LayerIndex];
var layer = doc.Layers.FirstOrDefault(x => x.ParentLayerId == parent.Id && x.Name == "Planes");
if (layer is null)
{
planesAtt.LayerIndex = doc.Layers.Add
(
new Layer
{
ParentLayerId = parent.Id,
Name = "Planes",
IsVisible = true,
//#if RHINO_8
// IsLocked = true
//#else
IsLocked = false
//#endif
}
);
layer = doc.Layers[index];
}
else
{
planesAtt.LayerIndex = layer.Index;
//#if !RHINO_8
if (layer.IsLocked) layer.IsLocked = false; // Allow me to center the planes please!!
//#endif
}

var planes = new (int Name, Plane Plane, Interval U, Interval V)[]
{
(0, new Plane(box.PointAt(0.0, 0.5, 0.5), box.Plane.YAxis, box.Plane.ZAxis), box.Y, box.Z), // left
(1, new Plane(box.PointAt(1.0, 0.5, 0.5), -box.Plane.YAxis, box.Plane.ZAxis), box.Y, box.Z), // right
(2, new Plane(box.PointAt(0.5, 0.0, 0.5), -box.Plane.XAxis, box.Plane.ZAxis), box.X, box.Z), // front
(3, new Plane(box.PointAt(0.5, 1.0, 0.5), box.Plane.XAxis, box.Plane.ZAxis), box.X, box.Z), // back
(4, new Plane(box.PointAt(0.5, 0.5, 0.0), box.Plane.XAxis, box.Plane.YAxis), box.X, box.Y), // bottom
(5, new Plane(box.PointAt(0.5, 0.5, 1.0), -box.Plane.XAxis, box.Plane.YAxis), box.X, box.Y) // top
};

planesAtt.AddToGroup(index);
planesAtt.ColorSource = ObjectColorSource.ColorFromObject;
planesAtt.ObjectColor = System.Drawing.Color.FromArgb(0); // Make planes "invisible"
planesAtt.PlotColorSource = ObjectPlotColorSource.PlotColorFromDisplay;
var name = 0;
foreach (var plane in planes)
{
viewportIds.TryGetValue(name++, out var viewports);
AddClippingPlane(doc, plane.Plane, viewports, planesAtt);
}

// This makes the gumball ignore the Planes even are visible.
layer.SetPersistentLocking(true);
layer.IsLocked = true;
}
}
}
}

if (guid != Guid.Empty)
{
idMap.Add(Id, guid);
return true;
}
}

return false;
}

private static ClippingPlaneObject AddClippingPlane(RhinoDoc document, Plane plane, IEnumerable<Guid> viewportIds, ObjectAttributes attributes)
{
var interval = new Interval(-Revit.ModelUnits * 3, +Revit.ModelUnits * 3);
//#if RHINO_8
// var surface = new PlaneSurface(plane, interval, interval);
// var clippingSurface = new ClippingPlaneSurface(surface);

// foreach (var vport in viewportIds ?? Array.Empty<Guid>())
// clippingSurface.AddClipViewportId(vport);

// clippingSurface.ParticipationListsEnabled = true;
// clippingSurface.SetClipParticipation(Array.Empty<Guid>(), new int[] { attributes.LayerIndex }, true);
// var id = document.Objects.Add(clippingSurface, attributes);
// var clippingPlane = document.Objects.Find(id) as ClippingPlaneObject;
//#else
var id = document.Objects.AddClippingPlane(plane, 3.0 * Revit.ModelUnits, 3.0 * Revit.ModelUnits, viewportIds ?? new Guid[] { Guid.Empty }, attributes);

var clippingPlane = document.Objects.Find(id) as ClippingPlaneObject;
var clippingSurface = clippingPlane.ClippingPlaneGeometry;

// Centered on the plane please!!
clippingSurface.Extend(0, interval);
clippingSurface.Extend(1, interval);
clippingPlane.CommitChanges();
//#endif

return clippingPlane;
}

public bool BakeInstanceDefinition
(
IDictionary<ARDB.ElementId, Guid> idMap,
bool overwrite,
RhinoDoc doc,
ObjectAttributes att,
out Guid guid
)
{
guid = Guid.Empty;
overwrite = false;

var box = new Box(Plane.WorldXY, new Interval(-0.5, +0.5), new Interval(-0.5, +0.5), new Interval(-0.5, +0.5));
box.Inflate(-0.001);

var name = "*Revit::Annotation::Scope Box";
var idef = doc.InstanceDefinitions.Find(name);
if (idef is object)
{
guid = idef.Id;
var objs = idef.GetObjects();
var bbox = BoundingBox.Empty;
foreach ( var obj in objs )
bbox.Union(obj.Geometry.GetBoundingBox(accurate: true));

overwrite |= (bbox.Min.X != box.X.T0 || bbox.Max.X != box.X.T1);
overwrite |= (bbox.Min.Y != box.Y.T0 || bbox.Max.Y != box.Y.T1);
overwrite |= (bbox.Min.Z != box.Z.T0 || bbox.Max.Z != box.Z.T1);
}
else overwrite = true;

if (overwrite)
{
var ibox = box;
var rectangles = new Rectangle3d[]
{
new Rectangle3d(new Plane(ibox.PointAt(0.0, 0.5, 0.5), ibox.Plane.YAxis, ibox.Plane.ZAxis), ibox.Y, ibox.Z), // left
new Rectangle3d(new Plane(ibox.PointAt(1.0, 0.5, 0.5), ibox.Plane.ZAxis, ibox.Plane.YAxis), ibox.Z, ibox.Y), // right
new Rectangle3d(new Plane(ibox.PointAt(0.5, 0.0, 0.5), ibox.Plane.ZAxis, ibox.Plane.XAxis), ibox.Z, ibox.X), // front
new Rectangle3d(new Plane(ibox.PointAt(0.5, 1.0, 0.5), ibox.Plane.XAxis, ibox.Plane.ZAxis), ibox.X, ibox.Z), // back
new Rectangle3d(new Plane(ibox.PointAt(0.5, 0.5, 0.0), ibox.Plane.XAxis, ibox.Plane.YAxis), ibox.X, ibox.Y), // bottom
new Rectangle3d(new Plane(ibox.PointAt(0.5, 0.5, 1.0), ibox.Plane.YAxis, ibox.Plane.XAxis), ibox.Y, ibox.X) // top
};

var geometry = rectangles.Select(x => new PolylineCurve(x.ToPolyline())).ToArray();

var attributes = new ObjectAttributes()
{
LayerIndex = att.LayerIndex,
ColorSource = ObjectColorSource.ColorFromParent,
LinetypeSource = ObjectLinetypeSource.LinetypeFromParent,
PlotColorSource = ObjectPlotColorSource.PlotColorFromParent,
MaterialSource = ObjectMaterialSource.MaterialFromParent,
};

if (idef is null)
{
var index = doc.InstanceDefinitions.Add(name, "Revit Scope Box", Point3d.Origin, geometry, Enumerable.Repeat(attributes, geometry.Length));
if (index >=0) guid = doc.InstanceDefinitions[index].Id;
}
else
{
if (doc.InstanceDefinitions.ModifyGeometry(idef.Index, geometry, Enumerable.Repeat(attributes, geometry.Length)))
guid = idef.Id;
}
}

return guid != Guid.Empty;
}
#endregion
}
}

0 comments on commit 940ed0e

Please sign in to comment.