/***************************************************/ private static FamilyInstance FamilyInstance_OneLevelBasedHosted(Document document, FamilySymbol familySymbol, XYZ origin, Transform orientation, Element host, RevitSettings settings) { if (host == null) { BH.Engine.Reflection.Compute.RecordError($"Element could not be created: instantiation of families with placement type of {familySymbol.Family.FamilyPlacementType} requires a host. ElementId: {familySymbol.Id.IntegerValue}"); return(null); } FamilyInstance familyInstance; if (orientation?.BasisX == null) { familyInstance = document.Create.NewFamilyInstance(origin, familySymbol, host, StructuralType.NonStructural); if (familyInstance == null) { return(null); } } else { familyInstance = document.Create.NewFamilyInstance(origin, familySymbol, orientation.BasisX, host, StructuralType.NonStructural); if (familyInstance == null) { return(null); } document.Regenerate(); if (1 - Math.Abs(familyInstance.GetTotalTransform().BasisY.DotProduct(orientation.BasisY.Normalize())) > settings.AngleTolerance) { BH.Engine.Reflection.Compute.RecordWarning($"The orientation used to create the family instance was not perpendicular to the face on which the instance was placed. The orientation out of plane has been ignored. ElementId: {familyInstance.Id.IntegerValue}"); } } XYZ location = (familyInstance.Location as LocationPoint)?.Point; if (location != null && location.DistanceTo(origin) > settings.DistanceTolerance) { List <Solid> hostSolids = host.Solids(new Options()); if (hostSolids == null && hostSolids.All(x => !origin.IsInside(x, settings.DistanceTolerance))) { BH.Engine.Reflection.Compute.RecordWarning($"The input location point for creation of a family instance was outside of the host solid, the point has been snapped to the host. ElementId: {familyInstance.Id.IntegerValue}"); } } return(familyInstance); }
/***************************************************/ public static bool SetLocation(this FamilyInstance element, IInstance instance, RevitSettings settings) { if (instance.Location == null) { return(false); } bool success = false; if (instance.Location is BH.oM.Geometry.Point) { LocationPoint location = element.Location as LocationPoint; if (location == null) { return(false); } XYZ newLocation = ((BH.oM.Geometry.Point)instance.Location).ToRevit(); if (location.Point.DistanceTo(newLocation) > settings.DistanceTolerance) { if (element.Host != null) { if (element.HostFace == null) { List <Solid> hostSolids = element.Host.Solids(new Options()); if (hostSolids != null && hostSolids.All(x => !newLocation.IsInside(x, settings.DistanceTolerance))) { BH.Engine.Reflection.Compute.RecordWarning($"The new location point used to update the location of a family instance was outside of the host solid, the point has been snapped to the host. BHoM_Guid: {instance.BHoM_Guid} ElementId: {element.Id.IntegerValue}"); } } else { if (element.Host is ReferencePlane) { Autodesk.Revit.DB.Plane p = ((ReferencePlane)element.Host).GetPlane(); if (p.Origin.DistanceTo(newLocation) > settings.DistanceTolerance && Math.Abs((p.Origin - newLocation).Normalize().DotProduct(p.Normal)) > settings.AngleTolerance) { BH.Engine.Reflection.Compute.RecordError($"Location update failed: the new location point used on update of a family instance does not lie in plane with its reference plane. BHoM_Guid: {instance.BHoM_Guid} ElementId: {element.Id.IntegerValue}"); return(false); } } else { Autodesk.Revit.DB.Face face = element.Host.GetGeometryObjectFromReference(element.HostFace) as Autodesk.Revit.DB.Face; XYZ toProject = newLocation; Transform instanceTransform = null; if (element.Host is FamilyInstance && !((FamilyInstance)element.Host).HasModifiedGeometry()) { instanceTransform = ((FamilyInstance)element.Host).GetTotalTransform(); toProject = (instanceTransform.Inverse.OfPoint(newLocation)); } IntersectionResult ir = face?.Project(toProject); if (ir == null) { BH.Engine.Reflection.Compute.RecordError($"Location update failed: the new location point used on update of a family instance could not be placed on its host face. BHoM_Guid: {instance.BHoM_Guid} ElementId: {element.Id.IntegerValue}"); return(false); } newLocation = ir.XYZPoint; if (instanceTransform != null) { newLocation = (instanceTransform.OfPoint(newLocation)); } if (ir.Distance > settings.DistanceTolerance) { BH.Engine.Reflection.Compute.RecordWarning($"The location point used on update of a family instance has been snapped to its host face. BHoM_Guid: {instance.BHoM_Guid} ElementId: {element.Id.IntegerValue}"); } } } } location.Point = newLocation; success = true; } if (instance.Orientation?.X != null) { Transform transform = element.GetTotalTransform(); XYZ newX = instance.Orientation.X.ToRevit().Normalize(); if (1 - Math.Abs(transform.BasisX.DotProduct(newX)) > settings.AngleTolerance) { XYZ revitNormal; XYZ bHoMNormal; FamilySymbol fs = element.Document.GetElement(element.GetTypeId()) as FamilySymbol; if (fs != null && fs.Family.FamilyPlacementType == FamilyPlacementType.OneLevelBasedHosted) { revitNormal = transform.BasisY; bHoMNormal = instance.Orientation.Y.ToRevit().Normalize(); } else { revitNormal = transform.BasisZ; bHoMNormal = instance.Orientation.Z.ToRevit().Normalize(); } if (1 - Math.Abs(revitNormal.DotProduct(bHoMNormal)) > settings.AngleTolerance) { BH.Engine.Reflection.Compute.RecordWarning($"The orientation applied to the family instance on update has different normal than the original one. Only in-plane rotation has been applied, the orientation out of plane has been ignored. BHoM_Guid: {instance.BHoM_Guid} ElementId: {element.Id.IntegerValue}"); } double angle = transform.BasisX.AngleOnPlaneTo(newX, revitNormal); if (Math.Abs(angle) > settings.AngleTolerance) { ElementTransformUtils.RotateElement(element.Document, element.Id, Autodesk.Revit.DB.Line.CreateBound(newLocation, newLocation + transform.BasisZ), angle); success = true; } } } } else if (instance.Location is ICurve && element.Host != null) { LocationCurve location = element.Location as LocationCurve; BH.oM.Geometry.Line l = instance.Location as BH.oM.Geometry.Line; if (location == null || l == null) { return(false); } XYZ start = l.Start.ToRevit(); XYZ end = l.End.ToRevit(); Transform instanceTransform = null; if (element.Host is FamilyInstance && !((FamilyInstance)element.Host).HasModifiedGeometry()) { instanceTransform = ((FamilyInstance)element.Host).GetTotalTransform(); start = (instanceTransform.Inverse.OfPoint(start)); end = (instanceTransform.Inverse.OfPoint(end)); } Autodesk.Revit.DB.Face face = element.Host.GetGeometryObjectFromReference(element.HostFace) as Autodesk.Revit.DB.Face; IntersectionResult ir1 = face?.Project(start); IntersectionResult ir2 = face?.Project(end); if (ir1 == null || ir2 == null) { BH.Engine.Reflection.Compute.RecordError($"Location update failed: the new location line used on update of a family instance could not be placed on its host face. BHoM_Guid: {instance.BHoM_Guid} ElementId: {element.Id.IntegerValue}"); return(false); } if (ir1.Distance > settings.DistanceTolerance || ir2.Distance > settings.DistanceTolerance) { BH.Engine.Reflection.Compute.RecordWarning($"The location line used on update of a family instance has been snapped to its host face. BHoM_Guid: {instance.BHoM_Guid} ElementId: {element.Id.IntegerValue}"); } start = ir1.XYZPoint; end = ir2.XYZPoint; if (instanceTransform != null) { start = instanceTransform.OfPoint(start); end = instanceTransform.OfPoint(end); } Autodesk.Revit.DB.Line newLocation = Autodesk.Revit.DB.Line.CreateBound(start, end); if (!newLocation.IsSimilar(location.Curve, settings)) { location.Curve = newLocation; success = true; } } else { success = SetLocation(element, instance.Location as dynamic, settings); } return(success); }