Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

6.3 Deployment #1406

Merged
merged 54 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
f428c0a
Upgrade AssemblyFileVersion to 6.3.0.0
BHoMBot Jun 23, 2023
1bcaa36
Remove Previous Version Attributes for 6.2
BHoMBot Jun 23, 2023
a752691
warnings about nonplanar faces added
pawelbaran Jun 23, 2023
7066b90
HasVisibleParameter method added
pawelbaran Jun 24, 2023
e58f377
descriptions added
pawelbaran Jun 24, 2023
3617d4f
copyright compliance fixed
pawelbaran Jun 28, 2023
848d50f
align viewport method created
michal-pekacki Jul 11, 2023
e636859
outline private methods added
michal-pekacki Jul 12, 2023
cfc0258
grouping viewports updated
michal-pekacki Jul 13, 2023
bddee87
organize outlines in row method created
michal-pekacki Jul 13, 2023
16f7675
update methods for vertical alignment
michal-pekacki Jul 13, 2023
6b6d0ba
right to left alignment added
michal-pekacki Jul 13, 2023
f6e57f2
changed align viewports to align outlines
michal-pekacki Jul 13, 2023
c2589f2
update after @vietle-bh comments
michal-pekacki Jul 17, 2023
8f27e5e
methods removed, null check added
michal-pekacki Jul 24, 2023
71dd298
added null check error
michal-pekacki Jul 27, 2023
215cd49
Update altConfigs file
Jul 31, 2023
4f70b7d
add DrawingArea for FamilyInstance
michal-pekacki Aug 4, 2023
a8aca64
update after @vietle-bh comments
michal-pekacki Aug 4, 2023
3bb6b19
changed RecordWarning to RecordError
michal-pekacki Aug 7, 2023
1edaa20
facade pull optimisation in progress
pawelbaran Aug 7, 2023
e81d80c
invalid mullions ruled out
pawelbaran Aug 7, 2023
670b8b9
check against invalid cells added
pawelbaran Aug 7, 2023
86100a5
extraction of edge mullions optimised
pawelbaran Aug 7, 2023
1478f89
curved walls accommodated
pawelbaran Aug 7, 2023
73bd253
code cleaned up
pawelbaran Aug 7, 2023
dda1416
commented out code deleted
pawelbaran Aug 7, 2023
03fcae2
private methods cleaned up
pawelbaran Aug 7, 2023
47fe9a6
typo fixed
pawelbaran Aug 8, 2023
5bd1a95
profile extraction introduced
pawelbaran Aug 8, 2023
19e7b09
material extraction unified for framing and mullions
pawelbaran Aug 8, 2023
1821cea
descriptions added
pawelbaran Aug 8, 2023
ec60f63
support for curtain systems added
pawelbaran Aug 9, 2023
6052546
conversion of individual panels and openings restored
pawelbaran Aug 9, 2023
815aedc
support for curtain systems extended to architecture and physical dis…
pawelbaran Aug 9, 2023
07556e6
input type of MullionElementProperty limited to Mullion
pawelbaran Aug 9, 2023
cca6ab6
FrameEdgeProperty creating dummy profiles removed
pawelbaran Aug 9, 2023
f6ae5cf
Mullion cloned to keep curve direction from flipping for panels
enarhi Aug 9, 2023
931cedc
Fixed CW ExternalEdge check to check per elemId
enarhi Aug 9, 2023
bbf5c72
Added rotation for mullion profile to fit BHoM FrameEdgeProperty stan…
enarhi Aug 9, 2023
cda87c4
tweaks following the review by @vietle-bh
pawelbaran Aug 10, 2023
87085ad
missing versioning added
pawelbaran Aug 18, 2023
7269e4e
`Create.Callout` added
michal-pekacki Aug 24, 2023
49a918d
input and description update
michal-pekacki Aug 24, 2023
4a0f1d1
view family added
michal-pekacki Aug 24, 2023
eb2559f
Fixed GetAllElementsVisibleInActiveView
vietle-bh Aug 30, 2023
57b6445
improve `Query.DrawingArea`
michal-pekacki Sep 1, 2023
567f5b7
code clean-up
michal-pekacki Sep 1, 2023
5183593
updated VisibilityLines, added family document close
michal-pekacki Sep 1, 2023
9c7e4a3
symbol family type null check added
michal-pekacki Sep 4, 2023
dc9970f
truss plane query added
pawelbaran Sep 2, 2023
5c3290d
Section view creation methods tweaked to allow for nonvertical sections
pawelbaran Sep 2, 2023
2467063
bugfix
pawelbaran Sep 2, 2023
7fec304
safety check added to avoid doc regeneration when not needed
pawelbaran Sep 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Revit_Adapter/Revit_Adapter.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<Authors>BHoM</Authors>
<Copyright>Copyright © https://github.com/BHoM</Copyright>
<RootNamespace>BH.Adapter.Revit</RootNamespace>
<FileVersion>6.2.0.0</FileVersion>
<FileVersion>6.3.0.0</FileVersion>
</PropertyGroup>

<PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion Revit_Core_Adapter/Revit_Core_Adapter.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<Authors>BHoM</Authors>
<Copyright>Copyright © https://github.com/BHoM</Copyright>
<RootNamespace>BH.Revit.Adapter.Core</RootNamespace>
<FileVersion>6.2.0.0</FileVersion>
<FileVersion>6.3.0.0</FileVersion>
</PropertyGroup>

<PropertyGroup>
Expand Down
49 changes: 41 additions & 8 deletions Revit_Core_Engine/Convert/Facade/FromRevit/CurtainWall.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,9 @@ public static CurtainWall CurtainWallFromRevit(this Wall wall, RevitSettings set
if (curtainPanels == null || !curtainPanels.Any())
BH.Engine.Base.Compute.RecordError(String.Format("Processing of panels of Revit curtain wall failed. BHoM curtain wall without location has been returned. Revit ElementId: {0}", wall.Id.IntegerValue));


// Get external edges of whole curtain wall
List<FrameEdge> extEdges = new List<FrameEdge>();
List<IElement1D> cwEdgeCrvs = curtainPanels.ExternalEdges();
foreach (ICurve crv in cwEdgeCrvs)
{
FrameEdge frameEdge = new FrameEdge { Curve = crv };
extEdges.Add(frameEdge);
}
List<FrameEdge> allEdges = curtainPanels.SelectMany(x => x.Edges).ToList();
List<FrameEdge> extEdges = allEdges.Distinct().Where(x => allEdges.Count(y => x.ElementId() == y.ElementId()) == 1).ToList();

bHoMCurtainWall = new CurtainWall { ExternalEdges = extEdges, Openings = curtainPanels.ToList(), Name = wall.WallType.Name };

Expand All @@ -95,6 +89,45 @@ public static CurtainWall CurtainWallFromRevit(this Wall wall, RevitSettings set
}

/***************************************************/

[Description("Converts a Revit Wall to BH.oM.Facade.Elements.CurtainSystem.")]
[Input("system", "Revit CurtainSystem to be converted.")]
[Input("settings", "Revit adapter settings to be used while performing the convert.")]
[Input("refObjects", "Optional, a collection of objects already processed in the current adapter action, stored to avoid processing the same object more than once.")]
[Output("curtainWall", "BH.oM.Facade.Elements.CurtainWall resulting from converting the input Revit CurtainSystem.")]
public static CurtainWall CurtainWallFromRevit(this CurtainSystem system, RevitSettings settings = null, Dictionary<string, List<IBHoMObject>> refObjects = null)
{
if (system == null)
return null;

settings = settings.DefaultIfNull();

CurtainWall bHoMCurtainWall = refObjects.GetValue<CurtainWall>(system.Id);
if (bHoMCurtainWall != null)
return bHoMCurtainWall;

IEnumerable<oM.Facade.Elements.Opening> curtainPanels = system.ICurtainGrids().SelectMany(x => x.FacadeCurtainPanels(system.Document, settings, refObjects)).ToList();

if (curtainPanels == null || !curtainPanels.Any())
BH.Engine.Base.Compute.RecordError(String.Format("Processing of panels of Revit curtain wall failed. BHoM curtain wall without location has been returned. Revit ElementId: {0}", system.Id.IntegerValue));

// Get external edges of whole curtain wall
List<FrameEdge> allEdges = curtainPanels.SelectMany(x => x.Edges).ToList();
List<FrameEdge> extEdges = allEdges.Distinct().Where(x => allEdges.Count(y => x == y) == 1).ToList();

bHoMCurtainWall = new CurtainWall { ExternalEdges = extEdges, Openings = curtainPanels.ToList(), Name = system.FamilyTypeFullName() };

//Set identifiers, parameters & custom data
bHoMCurtainWall.SetIdentifiers(system);
bHoMCurtainWall.CopyParameters(system, settings.MappingSettings);
bHoMCurtainWall.SetProperties(system, settings.MappingSettings);

refObjects.AddOrReplace(system.Id, bHoMCurtainWall);

return bHoMCurtainWall;
}

/***************************************************/
}
}

Expand Down
5 changes: 4 additions & 1 deletion Revit_Core_Engine/Convert/Facade/FromRevit/Opening.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ public static oM.Facade.Elements.Opening FacadeOpeningFromRevit(this FamilyInsta
if (opening != null)
return opening;

FrameEdgeProperty frameEdgeProperty = familyInstance.FrameEdgeProperty(settings, refObjects);
// Extraction of frame edge property from Revit FamilyInstance is not implemented yet
BH.Engine.Base.Compute.RecordWarning($"Extraction of frame edge property from a Revit opening is currently not supported, property set to null. ElementId: {familyInstance.Id.IntegerValue}");
FrameEdgeProperty frameEdgeProperty = null;

BH.oM.Geometry.ISurface location = familyInstance.OpeningSurface(host, settings);

List<FrameEdge> edges = new List<FrameEdge>();
Expand Down
108 changes: 106 additions & 2 deletions Revit_Core_Engine/Convert/Structure/FromRevit/Profile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public static partial class Convert
/***************************************************/
/**** Public Methods ****/
/***************************************************/

[Description("Converts a Revit FamilySymbol to BH.oM.Spatial.ShapeProfiles.IProfile.")]
[Input("familySymbol", "Revit FamilySymbol to be converted.")]
[Input("settings", "Revit adapter settings to be used while performing the convert.")]
Expand Down Expand Up @@ -131,6 +131,92 @@ public static IProfile ProfileFromRevit(this FamilySymbol familySymbol, RevitSet
return profile;
}

/***************************************************/

[Description("Converts a Revit MullionType to BH.oM.Spatial.ShapeProfiles.IProfile.")]
[Input("mullionType", "Revit MullionType to be converted.")]
[Input("settings", "Revit adapter settings to be used while performing the convert.")]
[Input("refObjects", "Optional, a collection of objects already processed in the current adapter action, stored to avoid processing the same object more than once.")]
[Output("profile", "BH.oM.Spatial.ShapeProfiles.IProfile resulting from converting the input Revit MullionType.")]
public static IProfile ProfileFromRevit(this MullionType mullionType, RevitSettings settings = null, Dictionary<string, List<IBHoMObject>> refObjects = null)
{
settings = settings.DefaultIfNull();

IProfile profile = refObjects.GetValue<IProfile>(mullionType.Id);
if (profile != null)
return profile;

// The algorithm below is so convoluted because mullion type does not have a profile
// Instead, one needs to extract the geometry of one of the instances
// The instance to be queried needs to have its start (bottom) face exposed
// In simple words, it needs to be the first mullion in a chain of mullions of same type

// First, take arbitrary mullion of a given type
Document doc = mullionType.Document;
Mullion representativeMullion = new FilteredElementCollector(doc)
.OfClass(typeof(FamilyInstance))
.Where(x => x is Mullion)
.Cast<Mullion>()
.FirstOrDefault(x => x.MullionType.Id.IntegerValue == mullionType.Id.IntegerValue && x.MullionLine() != null);

if (representativeMullion == null)
{
BH.Engine.Base.Compute.RecordError($"Profile could not be extracted from a mullion. ElementId: {mullionType.Id.IntegerValue}");
return null;
}

// Find the first mullion in the chain the arbitrary one belongs to
List<Mullion> allMullionsInWall = new FilteredElementCollector(doc)
.OfClass(typeof(FamilyInstance))
.Where(x => x is Mullion)
.Cast<Mullion>()
.Where(x => x.Host.Id.IntegerValue == representativeMullion.Host.Id.IntegerValue
&& x.MullionType.Id.IntegerValue == mullionType.Id.IntegerValue)
.ToList();

BH.oM.Geometry.Line line = representativeMullion.MullionLine();
BH.oM.Geometry.Vector direction = line.Direction();
foreach (Mullion candidateMullion in allMullionsInWall)
{
// Skip mullions that are not collinear with the representative mullion
BH.oM.Geometry.Line candidateLine = candidateMullion.MullionLine();
if (candidateLine == null || !candidateLine.IsCollinear(line))
continue;

// Update the representative mullion if the candidate:
// - is collinear (check above)
// - has the same direction
// - has start before the current representative mullion, counting along the mullion direction
if ((candidateLine.Start - line.Start).DotProduct(direction) > 0)
{
representativeMullion = candidateMullion;
line = candidateLine;
}
}

// Find the instance geometry and extract profile from it
Options options = new Options();
options.DetailLevel = ViewDetailLevel.Fine;
options.IncludeNonVisibleObjects = false;
GeometryInstance instance = representativeMullion.get_Geometry(options).FirstOrDefault(x => x is GeometryInstance) as GeometryInstance;
MullionType instanceSymbol = instance.Symbol as MullionType;
if (instanceSymbol != null)
profile = instanceSymbol.FreeFormProfileFromRevit(settings);

if (profile == null)
return null;

//Set identifiers, parameters & custom data
profile.SetIdentifiers(mullionType);
profile.CopyParameters(mullionType, settings.MappingSettings);
profile.SetProperties(mullionType, settings.MappingSettings);

profile.Name = mullionType.Name;
refObjects.AddOrReplace(mullionType.Id, profile);

return profile;
}


/***************************************************/
/**** Private Methods ****/
Expand Down Expand Up @@ -610,7 +696,7 @@ private static FreeFormProfile FreeFormProfileFromRevit(this FamilySymbol family
XYZ direction;
if (familySymbol.Family.FamilyPlacementType == FamilyPlacementType.CurveDrivenStructural)
direction = XYZ.BasisX;
else if (familySymbol.Family.FamilyPlacementType == FamilyPlacementType.TwoLevelsBased)
else if (familySymbol.Family.FamilyPlacementType == FamilyPlacementType.TwoLevelsBased || familySymbol is MullionType)
direction = XYZ.BasisZ;
else
{
Expand Down Expand Up @@ -714,6 +800,13 @@ private static FreeFormProfile FreeFormProfileFromRevit(this FamilySymbol family
if (adjustment.Length() > settings.DistanceTolerance)
profileCurves = profileCurves.Select(x => x.ITranslate(adjustment)).ToList();

// If Mullion, rotate 90 degrees to match orientation of Mullions on CurtainWalls per BHoM Standard of -X is Exterior, +X is Interior
if (familySymbol is MullionType)
{
double angle = -Math.PI * 0.5;
profileCurves = profileCurves.Select(x => x.IRotate(oM.Geometry.Point.Origin, Vector.ZAxis, angle)).ToList();
}

// Check if the curves are in the horizontal plane, if not then align them.
if (familySymbol.Family.FamilyPlacementType == FamilyPlacementType.CurveDrivenStructural)
{
Expand Down Expand Up @@ -753,6 +846,17 @@ private static Solid SingleSolid(this GeometryElement geometryElement)
return solid;
}

/***************************************************/

private static BH.oM.Geometry.Line MullionLine(this Mullion mullion)
{
Curve curve = mullion?.LocationCurve;
if (curve == null)
return null;
else
return new oM.Geometry.Line { Start = curve.GetEndPoint(0).PointFromRevit(), End = curve.GetEndPoint(1).PointFromRevit() };
}


/***************************************************/
/**** Private helpers ****/
Expand Down
74 changes: 74 additions & 0 deletions Revit_Core_Engine/Create/View/Callout.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* This file is part of the Buildings and Habitats object Model (BHoM)
* Copyright (c) 2015 - 2023, the respective contributors. All rights reserved.
*
* Each contributor holds copyright over their respective contributions.
* The project versioning (Git) records all such contribution source information.
*
*
* The BHoM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* The BHoM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

using Autodesk.Revit.DB;
using BH.oM.Base.Attributes;
using System.ComponentModel;

namespace BH.Revit.Engine.Core
{
public static partial class Create
{
/***************************************************/
/**** Public methods ****/
/***************************************************/

[Description("Creates the callout view visible on the referenced view.")]
[Input("referenceView", "View on which the callout will be visible. Callouts can be created on view plans, sections and detail views.")]
[Input("boundingBoxXyz", "Bounds of the callout.")]
[Input("calloutName", "Name of the callout view. If null, default name will be set.")]
[Input("viewFamily", "ViewFamily to be used by the callout view. Detail view family set as default can be used in all views except CeilingPlans and DraftingViews (in which it is recommended to use the same view family as the reference view).")]
[Input("calloutTemplateId", "Id of the template to be applied to the callout view. If null, no template will be set.")]
[Output("callout", "New callout view.")]
public static View Callout(this View referenceView, BoundingBoxXYZ boundingBoxXyz, string calloutName = null, ViewFamily viewFamily = ViewFamily.Detail, ElementId calloutTemplateId = null)
{
if (referenceView == null)
{
BH.Engine.Base.Compute.RecordError("Could not create a callout view based on null reference view.");
return null;
}
else if (boundingBoxXyz == null)
{
BH.Engine.Base.Compute.RecordError("Could not create a callout view based on a null bounding box.");
return null;
}

Document document = referenceView.Document;
ViewFamilyType viewFamilyType = Query.ViewFamilyType(document, viewFamily);

View callout = Autodesk.Revit.DB.ViewSection.CreateCallout(document, referenceView.Id, viewFamilyType.Id, boundingBoxXyz.Min, boundingBoxXyz.Max);

callout.SetViewTemplate(calloutTemplateId);

if (!string.IsNullOrEmpty(calloutName))
{
callout.SetViewName(calloutName);
}

return callout;
}

/***************************************************/

}
}

1 change: 0 additions & 1 deletion Revit_Core_Engine/Create/View/View3D.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ public static partial class Create
/**** Public Methods ****/
/***************************************************/

[PreviousVersion("6.2", "BH.Revit.Engine.Core.Create.View3D(Autodesk.Revit.DB.Document, System.String, Autodesk.Revit.DB.BoundingBoxXYZ, Autodesk.Revit.DB.ElementId, Autodesk.Revit.DB.ViewDetailLevel)")]
[Description("Creates and returns a new ISOMETRIC 3D view in the current Revit file.")]
[Input("document", "Revit current document to be processed.")]
[Input("viewName", "Optional, name of the new view.")]
Expand Down
32 changes: 32 additions & 0 deletions Revit_Core_Engine/Create/View/ViewSection/ViewSection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using System;
using System.ComponentModel;
using BH.oM.Base.Attributes;
using System.Linq;

namespace BH.Revit.Engine.Core
{
Expand Down Expand Up @@ -78,6 +79,37 @@ public static ViewSection ViewSection(this Document document, BoundingBoxXYZ bou
result.SetViewName(viewName);
}

// In case of non-vertical section, sometimes Revit rotates the views by 90 degrees compared to the provided input
// The lines below bring the view orientation back to the desirable shape
if (1 - Math.Abs(boundingBoxXyz.Transform.BasisY.DotProduct(XYZ.BasisZ)) > BH.oM.Geometry.Tolerance.Angle)
{
document.Regenerate();

// Check if the view got rotated and action if necessary
BoundingBoxXYZ cropBox = result.CropBox;
if (Math.Abs(cropBox.Transform.BasisX.DotProduct(boundingBoxXyz.Transform.BasisX)) < BH.oM.Geometry.Tolerance.Angle)
{
// Rotate the cropbox by 90 degrees
Element cropBoxElement = new FilteredElementCollector(document).OfCategory(BuiltInCategory.OST_Viewers).FirstOrDefault(x => x != result && x.Name == result.Name);
BoundingBoxXYZ boxOfCropBoxElement = cropBoxElement.get_BoundingBox(result);
ElementTransformUtils.RotateElement(document, cropBoxElement.Id, Line.CreateUnbound((boxOfCropBoxElement.Min + boxOfCropBoxElement.Max) / 2 + boxOfCropBoxElement.Transform.Origin, boundingBoxXyz.Transform.BasisZ), Math.PI / 2);

// Realign the crop box to show the desired part of the view
cropBox = result.CropBox;
BoundingBoxXYZ bbox = new BoundingBoxXYZ();
bbox.Enabled = true;

double xDomain = cropBox.Max.Y - cropBox.Min.Y;
double yDomain = cropBox.Max.X - cropBox.Min.X;
XYZ mid = (cropBox.Min + cropBox.Max) / 2;
bbox.Transform = cropBox.Transform;
bbox.Min = new XYZ(mid.X - xDomain / 2, mid.Y - yDomain / 2, result.CropBox.Min.Z);
bbox.Max = new XYZ(mid.X + xDomain / 2, mid.Y + yDomain / 2, result.CropBox.Max.Z);

result.CropBox = bbox;
}
}

return result;
}

Expand Down
Loading