public void CropAroundRoom(Room room, View view) //This provides the required shape now how to combine with the offset and tie into wall thickness { if (view != null) { IList <IList <BoundarySegment> > segments = room.GetBoundarySegments(new SpatialElementBoundaryOptions()); if (null != segments) //the room may not be bound { foreach (IList <BoundarySegment> segmentList in segments) { CurveLoop loop = new CurveLoop(); foreach (BoundarySegment boundarySegment in segmentList) { List <XYZ> points = boundarySegment.GetCurve().Tessellate().ToList(); for (int ip = 0; ip < points.Count - 1; ip++) { Line l = Line.CreateBound(points[ip], points[ip + 1]); loop.Append(l); } } ViewCropRegionShapeManager vcrShapeMgr = view.GetCropRegionShapeManager(); bool cropValid = vcrShapeMgr.IsCropRegionShapeValid(loop); if (cropValid) { vcrShapeMgr.SetCropShape(loop); break; // if more than one set of boundary segments for room, crop around the first one } } } } }
/// <summary> /// 调整viewPlan的尺寸并贴合选中房间 /// change a viewPlan to fix the selected room /// </summary> /// <param name="view"></param> /// <param name="tran"></param> /// <param name="viewOffseet"></param> public void ChangeViewFitRoom(ViewPlan view, Transaction tran, double viewOffseet) { if (view == null) { TaskDialog.Show("viewIsNull", "Can't find the type of View."); return; } //获得并设定房间的边界设定,并获取其边界集 DocSet.uidoc.ActiveView = view; SpatialElementBoundaryOptions opt = new SpatialElementBoundaryOptions(); opt.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Center;//房间边界设定,能变更获取的边界位置 IList <IList <BoundarySegment> > segments = DocSet.selRoom.GetBoundarySegments(opt); if (segments == null) { TaskDialog.Show("segementsIsNull", "can't get the BoundarySegment of room"); return; } ViewCropRegionShapeManager vcrShanpMgr = view.GetCropRegionShapeManager(); CurveLoop loop = new CurveLoop(); foreach (IList <BoundarySegment> segmentList in segments) { foreach (BoundarySegment segment in segmentList) { Curve curve = segment.GetCurve(); loop.Append(curve); } bool cropValid = vcrShanpMgr.IsCropRegionShapeValid(loop); if (cropValid) { //默认矩形 //TaskDialog.Show("cropValid", "the crop is shape Valid"); tran.Start("change the view crop region"); vcrShanpMgr.SetCropShape(loop); tran.Commit(); tran.Start("Remove Crop Region Shape"); vcrShanpMgr.RemoveCropRegionShape(); tran.Commit(); //TaskDialog.Show("ChangeView", "ChangeViewdone"); break; } } tran.Start("loop offset"); //TaskDialog.Show("!!!", "changeloop!"); loop = CurveLoop.CreateViaOffset(vcrShanpMgr.GetCropShape().First(), -1 * viewOffseet / 300, new XYZ(0, 0, 1)); vcrShanpMgr.SetCropShape(loop); tran.Commit(); DocSet.uidoc.ActiveView = view; }
public static View ViewPlan(this Document document, Autodesk.Revit.DB.Level level, string viewName = null, CurveLoop cropBox = null, ElementId viewTemplateId = null, ViewDetailLevel viewDetailLevel = ViewDetailLevel.Coarse) { View result = null; ViewFamilyType vft = Query.ViewFamilyType(document, ViewFamily.FloorPlan); result = Autodesk.Revit.DB.ViewPlan.Create(document, vft.Id, level.Id); Modify.SetViewDetailLevel(result, viewDetailLevel); if (cropBox != null) { try { ViewCropRegionShapeManager vcrShapeMgr = result.GetCropRegionShapeManager(); result.CropBoxVisible = true; vcrShapeMgr.SetCropShape(cropBox); } catch (Exception) { BH.Engine.Reflection.Compute.RecordWarning("Could not create the Floor Plan with the provided crop box. Check if the crop box is a valid geometry and if the view's designated template accepts it to change."); } } if (viewTemplateId != null) { try { result.ViewTemplateId = viewTemplateId; } catch (Exception) { BH.Engine.Reflection.Compute.RecordWarning("Could not apply the View Template of Id " + viewTemplateId + "'." + ". Please check if it's a valid ElementId."); } } if (!string.IsNullOrEmpty(viewName)) { try { #if (REVIT2018 || REVIT2019) result.ViewName = viewName; #else result.Name = viewName; #endif } catch { BH.Engine.Reflection.Compute.RecordWarning("There is already a view named '" + viewName + "'." + " It has been named '" + result.Name + "' instead."); } } return(result); }
//---------------------------------------------------------- public CurveLoop Get_CurveLoop(UIApplication uiapp, Document doc) { CurveLoop cl = null; try { view_plan_name_data item = (view_plan_name_data)view_tem.SelectedItem; ViewPlan view_plan = new FilteredElementCollector(doc).OfClass(typeof(ViewPlan)).Cast <ViewPlan>().First(x => x.Name == item.single_value); ViewCropRegionShapeManager vcrShapeMgr = view_plan.GetCropRegionShapeManager(); cl = vcrShapeMgr.GetCropShape()[0]; } catch (Exception ex) { MessageBox.Show(ex.Message); } return(cl); }
//---------------------------------------------------------- public void Apply_Crop(UIApplication uiapp, Document doc) { try { view_plan_name_data item_TEM = (view_plan_name_data)view_tem.SelectedItem; view_plan_name_data item = (view_plan_name_data)view_apply.SelectedItem; CurveLoop cl = Get_CurveLoop(uiapp, doc); ViewPlan view_plan = new FilteredElementCollector(doc).OfClass(typeof(ViewPlan)).Cast <ViewPlan>().First(x => x.Name == item.single_value); ViewCropRegionShapeManager vcrShapeMgr = view_plan.GetCropRegionShapeManager(); if (vcrShapeMgr.CanHaveShape) { vcrShapeMgr.SetCropShape(cl); } view_plan.Scale = item_TEM.view_plan.Scale; } catch (Exception ex) { MessageBox.Show(ex.Message); } }
public void CropAroundRoomWithOffset(Room room, View view) { List <XYZ> points = new List <XYZ>(); if (view != null) { IList <IList <BoundarySegment> > segments = room.GetBoundarySegments(new SpatialElementBoundaryOptions()); if (null != segments) { foreach (IList <BoundarySegment> segmentList in segments) { CurveLoop loop = new CurveLoop(); foreach (BoundarySegment boundarySegment in segmentList) { points.AddRange(boundarySegment.GetCurve().Tessellate()); } CurveLoop loop2 = new CurveLoop(); double offset = 2.0; XYZ normal = new XYZ(0, 0, -1); List <XYZ> pts = OffsetPoints(points, offset, normal).ToList(); for (int ip = 0; ip < points.Count - 1; ip++) { Line l = Line.CreateBound(pts[ip], pts[ip + 1]); loop2.Append(l); } ViewCropRegionShapeManager vcrShapeMgr = view.GetCropRegionShapeManager(); bool cropValid = vcrShapeMgr.IsCropRegionShapeValid(loop); if (cropValid) { vcrShapeMgr.SetCropShape(loop); break; } } } } }
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { Document doc = commandData.Application.ActiveUIDocument.Document; // Variables to store user input List <int> selectedIntIds; Element titleBlock; View viewTemplate; ViewFamilyType viewFamilyType; double sheetDrawingHeight; double sheetDrawingWidth; // Prompt window to collect user input using (InteriorElevationsWindow customWindow = new InteriorElevationsWindow(commandData)) { customWindow.ShowDialog(); selectedIntIds = customWindow.IntegerIds; titleBlock = customWindow.SelectedComboItemTitleBlock.Tag as Element; viewTemplate = customWindow.SelectedComboItemViewTemplate.Tag as View; viewFamilyType = customWindow.SelectedComboItemViewType.Tag as ViewFamilyType; #region Required elements for this tool // No required elements loaded if (titleBlock == null && viewTemplate == null && viewFamilyType == null) { TaskDialog.Show("Warning", "Please load a Elevation, a Title Block and create a View Template"); return(Result.Cancelled); } // No title block and elevation loaded else if (titleBlock == null && viewFamilyType == null) { TaskDialog.Show("Warning", "Please load a Elevation and a Title Block"); return(Result.Cancelled); } // No title block and view template else if (titleBlock == null && viewTemplate == null) { TaskDialog.Show("Warning", "Please load a Title Block and create a View Template"); return(Result.Cancelled); } // No elevation and view template else if (viewFamilyType == null && viewTemplate == null) { TaskDialog.Show("Warning", "Please load an Elevation and create a View Template"); return(Result.Cancelled); } // No elevation else if (viewFamilyType == null) { TaskDialog.Show("Warning", "Please load an Elevation"); return(Result.Cancelled); } // No title block else if (titleBlock == null) { TaskDialog.Show("Warning", "Please load a Title Block"); return(Result.Cancelled); } // No view template else if (titleBlock == null) { TaskDialog.Show("Warning", "Please create a view template"); return(Result.Cancelled); } #endregion // Room selected else if (selectedIntIds != null) { // Select first plan view FilteredElementCollector floorPlansCollector = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Views); View floorPlan = floorPlansCollector.Cast <View>().Where(v => v.ViewType == ViewType.FloorPlan).Where(v => v.IsTemplate == false).FirstOrDefault(); if (floorPlan == null) { TaskDialog.Show("Warning", "Please create a floor plan"); return(Result.Cancelled); } // Store rooms with elevations created List <string> roomsSucceeded = new List <string>(); // Collect rooms foreach (int id in selectedIntIds) { Room room = doc.GetElement(new ElementId(id)) as Room; // Retrieve boundaries IList <IList <BoundarySegment> > boundaries = Helpers.Helpers.SpatialBoundaries(room); // Check boundaries list is not empty if (boundaries != null) { // Retrieve doc annotation categories var annoCategories = Helpers.Helpers.AnnoCatIds(doc); #region Rectangular rooms without interior boundaries if (boundaries[0].Count == 4 && boundaries.Count == 1 && Helpers.Helpers.IsRectangle(boundaries[0])) { // Transaction Transaction t = new Transaction(doc, "Create Single Marker Interior Elevations"); t.Start(); List <XYZ> points = Helpers.Helpers.BoundaPoints(boundaries); XYZ centroid = Helpers.Helpers.Centroid(points); // Create sheet ViewSheet sheet = Helpers.HelpersView.CreateSheet(doc, titleBlock.Id, room.Number + "-" + "INTERIOR ELEVATIONS"); // Retrieve title block FamilyInstance tBlock = new FilteredElementCollector(doc, sheet.Id) .OfCategory(BuiltInCategory.OST_TitleBlocks) .FirstElement() as FamilyInstance; // Retrieve title block size double sheetHeight = tBlock.get_Parameter(BuiltInParameter.SHEET_HEIGHT).AsDouble(); double sheetWidth = tBlock.get_Parameter(BuiltInParameter.SHEET_WIDTH).AsDouble(); // Center of title block XYZ centerTitleBlock = new XYZ(sheetWidth / 2, sheetHeight / 2, 0); // Create elevation marker ElevationMarker marker = ElevationMarker.CreateElevationMarker(doc, viewFamilyType.Id, centroid, viewTemplate.Scale); // Place views on sheet var viewports = new List <Viewport>(); for (int i = 0; i < 4; i++) { // Create elevation View view = Helpers.HelpersView.CreateViewElevation(doc, marker, floorPlan, i, viewTemplate, annoCategories); Helpers.HelpersView.CreateViewport(doc, sheet, ref viewports, view); } // Dictionary to store viewport dimensions var viewportDims = Helpers.HelpersView.ViewportDimensions(viewports); // Retrieve overall dimensions List <double> firstRowX = new List <double>(); List <double> firstRowY = new List <double>(); List <double> secondRowX = new List <double>(); List <double> secondRowY = new List <double>(); foreach (KeyValuePair <Viewport, double[]> entry in viewportDims) { Viewport vp = entry.Key; string detailNumber = vp.get_Parameter(BuiltInParameter.VIEWER_DETAIL_NUMBER).AsString(); if (detailNumber == "1" || detailNumber == "2") { firstRowX.Add(entry.Value[0]); firstRowY.Add(entry.Value[1]); } else { secondRowX.Add(entry.Value[0]); secondRowY.Add(entry.Value[1]); } } // Calculate X spacing double spacingViewX = Helpers.Helpers.MillimetersToFeet(30); double overallX = spacingViewX; if (firstRowX.Sum() > secondRowX.Sum()) { overallX += firstRowX.Sum(); } else { overallX += secondRowX.Sum(); } // Calculate Y spacing double spacingViewY = Helpers.Helpers.MillimetersToFeet(30); double overallY = spacingViewY; if (firstRowY.Sum() > secondRowY.Sum()) { overallY += firstRowY.Sum(); } else { overallY += secondRowY.Sum(); } // Closest and furthest X points double centerTitleBlockX = centerTitleBlock.X; double furthestX = overallX / 2 + centerTitleBlockX; double closestX = centerTitleBlockX - overallX / 2; // Closest and furthest Y points double centerTitleBlockY = centerTitleBlock.Y; double furthestY = overallY / 2 + centerTitleBlockY; double closestY = centerTitleBlockY - overallY / 2; // Points boundary XYZ lowestRight = new XYZ(furthestX, closestY, 0); XYZ lowestLeft = new XYZ(closestX, closestY, 0); XYZ heightestLeft = new XYZ(closestX, furthestY, 0); XYZ heightestRight = new XYZ(furthestX, furthestY, 0); // Move viewports foreach (Viewport vp in viewports) { Outline vpOut = vp.GetBoxOutline(); Outline labelOut = vp.GetLabelOutline(); // Viewport dimensions XYZ maxPoint = vpOut.MaximumPoint; XYZ minPoint = vpOut.MinimumPoint; string detailNumber = vp.get_Parameter(BuiltInParameter.VIEWER_DETAIL_NUMBER).AsString(); if (detailNumber == "4") { XYZ lowRightPoint = new XYZ(maxPoint.X, minPoint.Y, 0); XYZ moveVec = lowestRight - lowRightPoint; ElementTransformUtils.MoveElement(doc, vp.Id, moveVec); } else if (detailNumber == "3") { XYZ lowLeftPoint = new XYZ(minPoint.X, minPoint.Y, 0); XYZ moveVec = lowestLeft - lowLeftPoint; ElementTransformUtils.MoveElement(doc, vp.Id, moveVec); } else if (detailNumber == "2") { XYZ highRightPoint = new XYZ(maxPoint.X, maxPoint.Y, 0); XYZ moveVec = heightestRight - highRightPoint; ElementTransformUtils.MoveElement(doc, vp.Id, moveVec); } else if (detailNumber == "1") { XYZ highLeftPoint = new XYZ(minPoint.X, maxPoint.Y, 0); XYZ moveVec = heightestLeft - highLeftPoint; ElementTransformUtils.MoveElement(doc, vp.Id, moveVec); } } // Append room number to success list roomsSucceeded.Add(room.Number); // Commit transaction t.Commit(); } #endregion #region Rest of rooms // When room has more or less than 4 sides else { // Offset distanceof the elevation marker double offsetElevation = Helpers.Helpers.MillimetersToFeet(-1000); // Vector Z XYZ zAxis = new XYZ(0, 0, 1); // Transaction to create single elevations Transaction t2 = new Transaction(doc, "Create single elevations"); t2.Start(); // Create sheet ViewSheet sheet = Helpers.HelpersView.CreateSheet(doc, titleBlock.Id, room.Number + "-" + "INTERIOR ELEVATIONS"); // Retrieve title block FamilyInstance tBlock = new FilteredElementCollector(doc, sheet.Id) .OfCategory(BuiltInCategory.OST_TitleBlocks) .FirstElement() as FamilyInstance; // Retrieve title block size double sheetHeight = tBlock.get_Parameter(BuiltInParameter.SHEET_HEIGHT).AsDouble(); double sheetWidth = tBlock.get_Parameter(BuiltInParameter.SHEET_WIDTH).AsDouble(); // Store viewports on sheet var viewports = new List <Viewport>(); // Loop through each boundary foreach (var boundary in boundaries[0]) { Curve originalCurve = boundary.GetCurve(); Curve offsetCurve = originalCurve.CreateOffset(offsetElevation, zAxis); // Curve centers XYZ origCenter = (originalCurve.GetEndPoint(0) + originalCurve.GetEndPoint(1)) / 2; XYZ offsetCenter = (offsetCurve.GetEndPoint(0) + offsetCurve.GetEndPoint(1)) / 2; // Vector marker to center of original boundary XYZ vec = origCenter - offsetCenter; // Create elevation marker ElevationMarker marker = ElevationMarker.CreateElevationMarker(doc, viewFamilyType.Id, offsetCenter, viewTemplate.Scale); // Calculate rotation angle double angle = Helpers.Helpers.AngleTwoVectors(new XYZ(0, 100, 0), vec); // Check the component X of the translated vector to new origin is positive // this means angle to rotate clockwise if (angle != 0 && vec.X > 0) { angle = angle * -1; } else if (angle != 0 && origCenter.X < offsetCenter.X && origCenter.X > 0) { // Angle remains the same } // Check if rotation needs to be 180 degrees else if (angle == 0 && origCenter.Y < offsetCenter.Y) { angle = Math.PI; } // Line along z axis Line zLine = Line.CreateBound(new XYZ(offsetCenter.X, offsetCenter.Y, offsetCenter.Z), new XYZ(offsetCenter.X, offsetCenter.Y, offsetCenter.Z + 10)); // Create Elevation View as marker needs to have at least one elevation to rotate View view = Helpers.HelpersView.CreateViewElevation(doc, marker, floorPlan, 1, viewTemplate, annoCategories); // Rotate in increments as Revit API adds 180 degrees to certain positive angles if (angle > 0) { double angleRemainder = angle; while (angleRemainder > 0) { double rotAngle = 0; if (angleRemainder > 0.6) { rotAngle = 0.6; } else { rotAngle = angleRemainder; } ElementTransformUtils.RotateElement(doc, marker.Id, zLine, rotAngle); angleRemainder -= rotAngle; } } // Rotate normally else { ElementTransformUtils.RotateElement(doc, marker.Id, zLine, angle); } // Retrieve crop shape ViewCropRegionShapeManager cropShapeManag = view.GetCropRegionShapeManager(); IList <CurveLoop> cropCurves = cropShapeManag.GetCropShape(); // Retrieve max and min height double minHeight = 0; double maxHeight = 0; foreach (Curve curve in cropCurves[0]) { XYZ point = curve.GetEndPoint(0); double height = point.Z; if (height > maxHeight) { maxHeight = height; } else if (height < minHeight) { minHeight = height; } } // Crop region offset double topOffset = Helpers.Helpers.MillimetersToFeet(25); // Create curves for crop region XYZ bottomStartPoint = offsetCurve.GetEndPoint(0); XYZ bottomEndPoint = offsetCurve.GetEndPoint(1); XYZ startBase = new XYZ(bottomStartPoint.X, bottomStartPoint.Y, bottomStartPoint.Z + minHeight); XYZ endBase = new XYZ(bottomEndPoint.X, bottomEndPoint.Y, bottomEndPoint.Z + minHeight); XYZ startTop = new XYZ(bottomStartPoint.X, bottomStartPoint.Y, bottomStartPoint.Z + maxHeight + topOffset); XYZ endTop = new XYZ(bottomEndPoint.X, bottomEndPoint.Y, bottomEndPoint.Z + maxHeight + topOffset); // Create CurveLoop for new crop shape List <Curve> curvesNewCrop = new List <Curve>(); // Create contiguous lines Line sideOne = Line.CreateBound(startBase, startTop); Line sideTwo = Line.CreateBound(endTop, endBase); Line top = Line.CreateBound(startTop, endTop); Line baseLine = Line.CreateBound(endBase, startBase); // Add the curves in order to the CurveLoop list curvesNewCrop.Add(baseLine); curvesNewCrop.Add(sideOne); curvesNewCrop.Add(top); curvesNewCrop.Add(sideTwo); // Apply new crop shape cropShapeManag.SetCropShape(CurveLoop.Create(curvesNewCrop)); // Update document to reflect new crop shape when placing viewports doc.Regenerate(); // Create viewports Helpers.HelpersView.CreateViewport(doc, sheet, ref viewports, view); } // Final viewport translation coordinates sheetDrawingHeight = Helpers.Helpers.MillimetersToFeet(customWindow.SheetDrawingHeight); sheetDrawingWidth = Helpers.Helpers.MillimetersToFeet(customWindow.SheetDrawingWidth); var viewportDims = Helpers.HelpersView.ViewportDimensions(viewports); var coordinates = Helpers.HelpersView.ViewportRowsColumns(viewportDims, sheetDrawingWidth, sheetDrawingHeight); for (int i = 0; i < viewports.Count; i++) { ElementTransformUtils.MoveElement(doc, viewports[i].Id, coordinates[i]); } // Append room number to success list roomsSucceeded.Add(room.Number); // Commit transaction t2.Commit(); } #endregion } } #region Display results to user // Display results to user if (roomsSucceeded.Count > 0) { string messageSuccess = string.Join("\n", roomsSucceeded.ToArray()); TaskDialog.Show("Success", "The following room elevations have been created: " + "\n" + messageSuccess); } else { TaskDialog.Show("Error", "No room elevations have been created"); } #endregion } } return(Result.Succeeded); }
private static bool GetCalloutCornerPoints(Document doc, ElementId calloutId, out XYZ firstPoint, out XYZ secondPoint) { bool result = false; firstPoint = new XYZ(0, 0, 0); secondPoint = new XYZ(0, 0, 0); try { double minX = double.MaxValue; double minY = double.MaxValue; double minZ = double.MaxValue; double maxX = double.MinValue; double maxY = double.MinValue; double maxZ = double.MinValue; ViewCropRegionShapeManager cropRegion = View.GetCropRegionShapeManagerForReferenceCallout(doc, calloutId); #if RELEASE2016 || RELEASE2017 IList <CurveLoop> curveLoops = cropRegion.GetCropShape(); foreach (CurveLoop cLoop in curveLoops) { foreach (Curve curve in cLoop) { XYZ point = curve.GetEndPoint(0); if (point.X < minX) { minX = point.X; } if (point.Y < minY) { minY = point.Y; } if (point.Z < minZ) { minZ = point.Z; } if (point.X > maxX) { maxX = point.X; } if (point.Y > maxY) { maxY = point.Y; } if (point.Z > maxZ) { maxZ = point.Z; } } } if (curveLoops.Count() > 0) { firstPoint = new XYZ(minX, minY, minZ); secondPoint = new XYZ(maxX, maxY, maxZ); result = true; } #else CurveLoop curveLoop = cropRegion.GetCropRegionShape(); foreach (Curve curve in curveLoop) { XYZ point = curve.GetEndPoint(0); if (point.X < minX) { minX = point.X; } if (point.Y < minY) { minY = point.Y; } if (point.Z < minZ) { minZ = point.Z; } if (point.X > maxX) { maxX = point.X; } if (point.Y > maxY) { maxY = point.Y; } if (point.Z > maxZ) { maxZ = point.Z; } } if (curveLoop.Count() > 0) { firstPoint = new XYZ(minX, minY, minZ); secondPoint = new XYZ(maxX, maxY, maxZ); result = true; } #endif } catch (Exception ex) { errorMessage.AppendLine("Failed to get corner points of callout.\n" + ex.Message); //MessageBox.Show("Failed to get corner points of callout\n" + ex.Message, "Get Corner Points of Callout", MessageBoxButton.OK, MessageBoxImage.Warning); } return(result); }
public static void AlignViews(Document doc, List <ExportSheet> selectedSheets, ExportSheet selectedSheet) { var viewPorts = selectedSheet.Sheet.GetAllViewports(); if (viewPorts.Count != 1) { return; } /// Save template view crops var firstViewportId = viewPorts.First(); var firstViewport = doc.GetElement(firstViewportId) as Autodesk.Revit.DB.Viewport; var templateView = doc.GetElement(firstViewport.ViewId) as Autodesk.Revit.DB.View; bool templateViewCropEnabled = templateView.CropBox.Enabled; if (!templateViewCropEnabled) { templateView.CropBox.Enabled = true; templateView.CropBox = templateView.get_BoundingBox(templateView); doc.Regenerate(); } var templateViewOriginalBoxOutline = firstViewport.GetBoxOutline(); var templateViewOriginalCenter = firstViewport.GetBoxCenter(); var templateViewOriginaCrop = templateView.CropBox; var templateViewScopeBoxParam = templateView.LookupParameter("Scope Box"); var templateViewScopeBoxID = templateViewScopeBoxParam.AsElementId(); bool templateViewHasScopeBox = templateViewScopeBoxID != ElementId.InvalidElementId; if (!templateViewCropEnabled) { templateView.CropBox.Enabled = false; } using (var transaction = new Transaction(doc)) { if (transaction.Start("Align Views") == TransactionStatus.Started) { foreach (var sheet in selectedSheets) { // Don't align template sheet views if (sheet != selectedSheet) { var vps = sheet.Sheet.GetAllViewports(); if (vps.Count == 1) { var destViewport = doc.GetElement(vps.First()) as Autodesk.Revit.DB.Viewport; var destView = doc.GetElement(destViewport.ViewId) as Autodesk.Revit.DB.View; var desteViewScopeBoxParam = destView.LookupParameter("Scope Box"); var destViewScopeBoxID = desteViewScopeBoxParam.AsElementId(); bool destViewHasScopeBox = destViewScopeBoxID != ElementId.InvalidElementId; var ob = destViewport.GetBoxOutline(); // try to remove the scope box temporarily if (!desteViewScopeBoxParam.IsReadOnly) { desteViewScopeBoxParam.Set(ElementId.InvalidElementId); } // set the crop to match the template view bool destViewHasCropShape = false; IList <CurveLoop> oldShape = null; ViewCropRegionShapeManager destViewCropManager = null; if (destView.ViewType != ViewType.Elevation && destView.ViewType != ViewType.Section) { destViewCropManager = destView.GetCropRegionShapeManager(); destViewHasCropShape = destViewCropManager.ShapeSet; oldShape = destViewCropManager.GetCropShape(); destViewCropManager.RemoveCropRegionShape(); } if (destView.ViewType == ViewType.Elevation || destView.ViewType == ViewType.Section) { var newCrop = new BoundingBoxXYZ(); newCrop.Min = new XYZ(destView.CropBox.Min.X, destView.CropBox.Min.Y, templateView.CropBox.Min.Z); newCrop.Max = new XYZ(destView.CropBox.Max.X, destView.CropBox.Max.Y, templateView.CropBox.Max.Z); destView.CropBox = newCrop; destView.CropBox.Enabled = true; } else { destView.CropBox = templateViewOriginaCrop; destView.CropBox.Enabled = true; } // regenerate just in case doc.Regenerate(); var destViewportBoxOutline = destViewport.GetBoxOutline(); var destViewportOriginalBoxOutline = destViewport.GetBoxOutline(); if (destView.ViewType == ViewType.Elevation || destView.ViewType == ViewType.Section) { var min = templateViewOriginalBoxOutline.MinimumPoint; var max = templateViewOriginalBoxOutline.MaximumPoint; var newMin = new XYZ( destViewportBoxOutline.MinimumPoint.X, min.Y, destViewportBoxOutline.MinimumPoint.Z); var newMax = new XYZ( destViewportBoxOutline.MaximumPoint.X, max.Y, destViewportBoxOutline.MaximumPoint.Z); Outline ol = new Outline(newMin, newMax); destViewportBoxOutline = ol; } else { destViewportBoxOutline = templateViewOriginalBoxOutline; } if (destView.ViewType == ViewType.Elevation || destView.ViewType == ViewType.Section) { var newCenter = new XYZ( destViewport.GetBoxCenter().X, templateViewOriginalCenter.Y, destViewport.GetBoxCenter().Z); destViewport.SetBoxCenter(newCenter); } else { destViewport.SetBoxCenter(templateViewOriginalCenter); } // reset crop and scope if (!desteViewScopeBoxParam.IsReadOnly) { desteViewScopeBoxParam.Set(destViewScopeBoxID); } if (destView.ViewType != ViewType.Elevation && destView.ViewType != ViewType.Section) { destViewportBoxOutline = destViewportOriginalBoxOutline; if (destViewHasCropShape) { destViewCropManager.SetCropShape(oldShape.First()); } } } } } transaction.Commit(); } else { transaction.RollBack(); } } }
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; IList <double> wallthicknessList = new List <double>(); XYZ normal = new XYZ(0, 0, 1); string previous = null; double previousWidth = 0; SpatialElementBoundaryOptions seb_opt = new SpatialElementBoundaryOptions(); FilteredElementCollector levels = new FilteredElementCollector(doc).OfClass(typeof(Level)); using (Transaction tx = new Transaction(doc)) { tx.Start("Create cropped views for each room"); string date_iso = DateTime.Now.ToString("yyyy-MM-dd"); foreach (Level level in levels) { Debug.Print(level.Name); ElementId id_view = level.FindAssociatedPlanViewId(); ViewPlan view = doc.GetElement(id_view) as ViewPlan; IEnumerable <Room> rooms = new FilteredElementCollector(doc, id_view).OfClass(typeof(SpatialElement)).Where <Element>(e => e is Room).Cast <Room>(); foreach (Room room in rooms) { wallthicknessList.Clear(); string view_name = string.Format("{0}_cropped_to_room_{1}_date_{2}", view.Name, room.Name, date_iso); id_view = view.Duplicate(ViewDuplicateOption.AsDependent); View view_cropped = doc.GetElement(id_view) as View; view_cropped.Name = view_name; IList <IList <BoundarySegment> > sloops = room.GetBoundarySegments(seb_opt); if (null == sloops) // the room may not be bound { continue; } CurveLoop loop = null; foreach (IList <BoundarySegment> sloop in sloops) { loop = new CurveLoop(); foreach (BoundarySegment s in sloop) { loop.Append(s.GetCurve()); ElementType type = doc.GetElement(s.ElementId) as ElementType; Element elem = doc.GetElement(s.ElementId); //Error when wall width varies across length //if (elem is Wall) //{ // Wall wall = elem as Wall; // wallthicknessList.Add(wall.Width*1.1); //} //else //{ // //Room separator // //Any other exceptions to walls need including?? // wallthicknessList.Add(0); //} if (elem != null)//The elem == null is due to room separators. Are there going to be any others? { if (firstPass) { if ((BuiltInCategory)elem.Category.Id.IntegerValue == BuiltInCategory.OST_Walls) { Wall wall = elem as Wall; //Is there a better way of identifying Orientation (predominantly horizontal or Vertical) What if walls at 45 deg? if (Math.Abs(Math.Round(wall.Orientation.Y, 0)) == 1) { previous = "Y"; } else { previous = "X"; } firstPass = false; wallthicknessList.Add(wall.Width + 0.1); previousWidth = wall.Width + 0.1; } //Are there any other situations need taking account off? else if ((BuiltInCategory)elem.Category.Id.IntegerValue == BuiltInCategory.OST_RoomSeparationLines) { //Room separator Autodesk.Revit.DB.Options opt = new Options(); Autodesk.Revit.DB.GeometryElement geomElem = elem.get_Geometry(opt); foreach (GeometryObject geomObj in geomElem) { Line line = geomObj as Line; //Is there a better way of identifying Orientation (predominantly horizontal or Vertical) What if walls at 45 deg? if (0 - line.GetEndPoint(1).X - line.GetEndPoint(0).X > 0 - line.GetEndPoint(1).Y - line.GetEndPoint(0).Y) { previous = "Y"; } else { previous = "X"; } firstPass = false; wallthicknessList.Add(0.1); previousWidth = 0.1; } } } else { if ((BuiltInCategory)elem.Category.Id.IntegerValue == BuiltInCategory.OST_Walls) { Wall wall = elem as Wall; if (Math.Abs(Math.Round(wall.Orientation.Y, 0)) == 1 && previous == "Y") { if (wall.Width > previousWidth) { //This would appear to avoid the Cannot properly trim error //How to allow for more than two wall thickness changes within the same length? //How to not require this and just offset wall widths? wallthicknessList[wallthicknessList.Count - 1] = wall.Width + 0.1; } wallthicknessList.Add(wall.Width + 0.1); previousWidth = wall.Width + 0.1; previous = "Y"; } else if (Math.Abs(Math.Round(wall.Orientation.X, 0)) == 1 && previous == "X") { if (wall.Width > previousWidth) { //This would appear to avoid the Cannot properly trim error //How to allow for more than two wall thickness changes within the same length? //How to not require this and just offset wall widths? wallthicknessList[wallthicknessList.Count - 1] = wall.Width + 0.1; } wallthicknessList.Add(wall.Width + 0.1); previousWidth = wall.Width + 0.1; previous = "X"; } else { if (Math.Abs(Math.Round(wall.Orientation.Y, 0)) == 1) { previous = "Y"; } else if (Math.Abs(Math.Round(wall.Orientation.X, 0)) == 1) { previous = "X"; } wallthicknessList.Add(wall.Width + 0.1); previousWidth = wall.Width + 0.1; } } else if ((BuiltInCategory)elem.Category.Id.IntegerValue == BuiltInCategory.OST_RoomSeparationLines)//Any other situations need taking account of? { //Room separator Autodesk.Revit.DB.Options opt = new Options(); Autodesk.Revit.DB.GeometryElement geomElem = elem.get_Geometry(opt); foreach (GeometryObject geomObj in geomElem) { Line line = geomObj as Line; //Is there a better way of identifying Orientation (predominantly horizontal or Vertical) What if walls at 45 deg? if (0 - line.GetEndPoint(1).X - line.GetEndPoint(0).X > 0 - line.GetEndPoint(1).Y - line.GetEndPoint(0).Y) { previous = "Y"; } else { previous = "X"; } wallthicknessList.Add(previousWidth); //Error "cannot trim" //wallthicknessList.Add(0.1); previousWidth = 0.1; } } } } else { wallthicknessList.Add(-0.1); } } // Skip out after first sloop - ignore // rooms with holes and disjunct parts break; } CurveLoop loop2 = CurveLoop.CreateViaOffset(loop, wallthicknessList, normal); CurveLoop newloop = new CurveLoop(); foreach (Curve curve in loop2) { List <XYZ> points = curve.Tessellate().ToList(); for (int ip = 0; ip < points.Count - 1; ip++) { Line l = Line.CreateBound(points[ip], points[ip + 1]); newloop.Append(l); } } ViewCropRegionShapeManager vcrs_mgr = view_cropped.GetCropRegionShapeManager(); bool valid = vcrs_mgr.IsCropRegionShapeValid(newloop); if (valid) { view_cropped.CropBoxVisible = true; view_cropped.CropBoxActive = true; vcrs_mgr.SetCropShape(newloop); } } } tx.Commit(); } return(Result.Succeeded); }
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; IList <double> wallthicknessList = new List <double>(); XYZ normal = new XYZ(0, 0, 1); SpatialElementBoundaryOptions seb_opt = new SpatialElementBoundaryOptions(); FilteredElementCollector levels = new FilteredElementCollector(doc).OfClass(typeof(Level)); using (Transaction tx = new Transaction(doc)) { tx.Start("Create cropped views for each room"); string date_iso = DateTime.Now.ToString("yyyy-MM-dd"); foreach (Level level in levels) { wallthicknessList.Clear(); Debug.Print(level.Name); ElementId id_view = level.FindAssociatedPlanViewId(); ViewPlan view = doc.GetElement(id_view) as ViewPlan; IEnumerable <Room> rooms = new FilteredElementCollector(doc, id_view).OfClass(typeof(SpatialElement)).Where <Element>(e => e is Room).Cast <Room>(); foreach (Room room in rooms) { wallthicknessList.Clear(); string view_name = string.Format("{0}_cropped_to_room_{1}_date_{2}", view.Name, room.Name, date_iso); id_view = view.Duplicate(ViewDuplicateOption.AsDependent); View view_cropped = doc.GetElement(id_view) as View; view_cropped.Name = view_name; IList <IList <BoundarySegment> > sloops = room.GetBoundarySegments(seb_opt); if (null == sloops) // the room may not be bound { continue; } CurveLoop loop = null; foreach (IList <BoundarySegment> sloop in sloops) { loop = new CurveLoop(); foreach (BoundarySegment s in sloop) { loop.Append(s.GetCurve()); ElementType type = doc.GetElement(s.ElementId) as ElementType; Element elem = doc.GetElement(s.ElementId); if (elem is Wall) { Wall wall = elem as Wall; wallthicknessList.Add(wall.Width); } else { //Room separator //Any other exceptions to walls need including?? wallthicknessList.Add(0); } } // Skip out after first sloop - ignore // rooms with holes and disjunct parts break; } CurveLoop loop2 = CurveLoop.CreateViaOffset(loop, wallthicknessList, normal); CurveLoop newloop = new CurveLoop(); foreach (Curve curve in loop2) { List <XYZ> points = curve.Tessellate().ToList(); for (int ip = 0; ip < points.Count - 1; ip++) { Line l = Line.CreateBound(points[ip], points[ip + 1]); newloop.Append(l); } } ViewCropRegionShapeManager vcrs_mgr = view_cropped.GetCropRegionShapeManager(); bool valid = vcrs_mgr.IsCropRegionShapeValid(newloop); if (valid) { view_cropped.CropBoxVisible = true; view_cropped.CropBoxActive = true; vcrs_mgr.SetCropShape(newloop); } } } tx.Commit(); } return(Result.Succeeded); }
public ViewsCEPRRequest(UIApplication uiApp, String text) { MainUI uiForm = BARevitTools.Application.thisApp.newMainUi; UIDocument uidoc = uiApp.ActiveUIDocument; //Collect the ViewTypes in the project FilteredElementCollector viewTypesCollector = new FilteredElementCollector(uidoc.Document); ICollection <Element> viewTypes = viewTypesCollector.OfClass(typeof(ViewFamilyType)).ToElements(); ElementId viewTypeId = null; //Cycle through the ViewType elements to find the one with a type name equal to the one selected in the MainUI's combobox foreach (ViewFamilyType viewType in viewTypes) { if (viewType.get_Parameter(BuiltInParameter.ALL_MODEL_TYPE_NAME).AsString() == uiForm.viewsCEPRElevationComboBox.Text) { viewTypeId = viewType.Id; } } //If the ViewType was found, and the active view is a plan view, continue if (viewTypeId != null && uidoc.ActiveView.GetType().ToString() == "Autodesk.Revit.DB.ViewPlan") { //Invoke a room selection List <Room> selectedRoomElements = RVTOperations.SelectRoomElements(uiApp); //If the user selected rooms, continue if (selectedRoomElements != null) { try { //Cycle through each selected room foreach (Room room in selectedRoomElements) { //First, get the room number for use in generating the elevation view names string roomNumber = room.Number; string roomName = room.get_Parameter(BuiltInParameter.ROOM_NAME).AsString().ToUpper(); //Get the geometry of the room Options geomOptions = new Options(); geomOptions.IncludeNonVisibleObjects = true; GeometryElement geomElements = room.get_Geometry(geomOptions); //Get the location point of the room as a point for where to place the elevation marker LocationPoint roomLocation = room.Location as LocationPoint; XYZ point = roomLocation.Point; //Start a transaction Transaction t1 = new Transaction(uidoc.Document, "Create Elevations Per Room"); t1.Start(); try { //Make a new ElevationMarker that uses the ViewType earlier, the location point of the room, and has a view scale of 1/8" ElevationMarker newMarker = ElevationMarker.CreateElevationMarker(uidoc.Document, viewTypeId, point, 96); //Start making views going around the elevation marker where the indexes start on the west side and go clockwise ViewSection view0 = newMarker.CreateElevation(uidoc.Document, uidoc.ActiveView.Id, 0); //Set the view name equal to the room number + room name + plus orientation view0.Name = roomNumber + " " + roomName + " WEST"; view0.CropBoxActive = true; //Repeat for the other view directions at their appropriate index ViewSection view1 = newMarker.CreateElevation(uidoc.Document, uidoc.ActiveView.Id, 1); view1.Name = roomNumber + " " + roomName + " NORTH"; view1.CropBoxActive = true; ViewSection view2 = newMarker.CreateElevation(uidoc.Document, uidoc.ActiveView.Id, 2); view2.Name = roomNumber + " " + roomName + " EAST"; view2.CropBoxActive = true; ViewSection view3 = newMarker.CreateElevation(uidoc.Document, uidoc.ActiveView.Id, 3); view3.Name = roomNumber + " " + roomName + " SOUTH"; view3.CropBoxActive = true; //Make a Solid object for assignment Solid roomSolid = null; //The following section is dedicated to cropping the elevation views to the cross-section of the room geometry if (uiForm.viewsCEPRCropCheckBox.Checked == true) { //Cycle through the geometry elements associated with the room geometry until the solid is found foreach (GeometryObject geom in geomElements) { if (geom.GetType().ToString() == "Autodesk.Revit.DB.Solid") { roomSolid = geom as Solid; break; } } //Generate 4 planes at the room point that will correspond to each elevation view's cross section of the room geometry // Each plane's normal vector is in the direction their view is facing Plane westPlane = Plane.CreateByNormalAndOrigin(new XYZ(-1, 0, 0), point); //-X vector for West Plane northPlane = Plane.CreateByNormalAndOrigin(new XYZ(0, 1, 0), point); //+Y vector for North Plane eastPlane = Plane.CreateByNormalAndOrigin(new XYZ(1, 0, 0), point); //+X vector for East Plane southPlane = Plane.CreateByNormalAndOrigin(new XYZ(0, -1, 0), point); //-Y vector for South //Use the room section's perimeter as the crop boundary if the first index of the MainUI combobox is selected if (uiForm.viewsCEPRCropMethodComboBox.SelectedIndex == 0) { try { //Generate some CurveLoop lists for use later IList <CurveLoop> westCurveLoopsFitted = null; IList <CurveLoop> northCurveLoopsFitted = null; IList <CurveLoop> southCurveLoopsFitted = null; IList <CurveLoop> eastCurveLoopsFitted = null; //Slice the room solid with the westPlane object made earlier. This will result in a solid boolean result to the west of the plane because the positive side of the plane faces west Solid westBooleanSolid = BooleanOperationsUtils.CutWithHalfSpace(roomSolid, westPlane); //Grab the faces of the solid that resulted from the boolean FaceArray westBoolSolidFaces = westBooleanSolid.Faces; //Cycle through each face and get the normal vector foreach (PlanarFace westFace in westBoolSolidFaces) { //For the west elevation face to use as the crop boundary, we need the face that has a vector going east, or the +X vector XYZ westFaceNormal = westFace.FaceNormal; if (westFaceNormal.X == 1) { //Get the edges as a CurveLoops once the face is found, then jump out of the loop thorugh the faces westCurveLoopsFitted = westFace.GetEdgesAsCurveLoops(); break; } } //Repeat for the north elevation Solid northBooleanSolid = BooleanOperationsUtils.CutWithHalfSpace(roomSolid, northPlane); FaceArray northBoolSolidFaces = northBooleanSolid.Faces; foreach (PlanarFace northFace in northBoolSolidFaces) { XYZ northFaceNormal = northFace.FaceNormal; if (northFaceNormal.Y == -1) { northCurveLoopsFitted = northFace.GetEdgesAsCurveLoops(); break; } } //Repeat for the east elevation Solid eastBooleanSolid = BooleanOperationsUtils.CutWithHalfSpace(roomSolid, eastPlane); FaceArray eastBoolSolidFaces = eastBooleanSolid.Faces; foreach (PlanarFace eastFace in eastBoolSolidFaces) { XYZ eastFaceNormal = eastFace.FaceNormal; if (eastFaceNormal.X == -1) { eastCurveLoopsFitted = eastFace.GetEdgesAsCurveLoops(); break; } } //Repeat for the south elevation Solid southBooleanSolid = BooleanOperationsUtils.CutWithHalfSpace(roomSolid, southPlane); FaceArray southBoolSolidFaces = southBooleanSolid.Faces; foreach (PlanarFace southFace in southBoolSolidFaces) { XYZ southFaceNormal = southFace.FaceNormal; if (southFaceNormal.Y == 1) { southCurveLoopsFitted = southFace.GetEdgesAsCurveLoops(); break; } } //To get the CurveLoop fitted 0.5" offset to the boundary of the face retrieved, create a CurveLoop via an offset //Now, the original curve loop was drawn on a plane with a +X axis vector normal, so the offset must be made in the positive X axis plane as well CurveLoop offsetWestCurveLoopFitted = CurveLoop.CreateViaOffset(westCurveLoopsFitted[0], (0.5d / 12), XYZ.BasisX); ViewCropRegionShapeManager westCropRegionShapeManager = view0.GetCropRegionShapeManager(); westCropRegionShapeManager.SetCropShape(offsetWestCurveLoopFitted); //Repeat for the north CurveLoop //Note that because the plane has a -Y vector, the offset needs to be negative too CurveLoop offsetNorthCurveLoopFitted = CurveLoop.CreateViaOffset(northCurveLoopsFitted[0], -(0.5d / 12), XYZ.BasisY);; ViewCropRegionShapeManager northCropRegionShapeManager = view1.GetCropRegionShapeManager(); northCropRegionShapeManager.SetCropShape(offsetNorthCurveLoopFitted); //Repeat for the east CurveLoop CurveLoop offsetEastCurveLoopFitted = CurveLoop.CreateViaOffset(eastCurveLoopsFitted[0], -(0.5d / 12), XYZ.BasisX);; ViewCropRegionShapeManager eastCropRegionShapeManager = view2.GetCropRegionShapeManager(); eastCropRegionShapeManager.SetCropShape(offsetEastCurveLoopFitted); //Repeat for the south CurveLoop CurveLoop offsetSouthCurveLoopFitted = CurveLoop.CreateViaOffset(southCurveLoopsFitted[0], (0.5d / 12), XYZ.BasisY);; ViewCropRegionShapeManager southCropRegionShapeManager = view3.GetCropRegionShapeManager(); southCropRegionShapeManager.SetCropShape(offsetSouthCurveLoopFitted); } catch (Exception e) { MessageBox.Show(e.ToString()); } } //Use the room section's rectangular extents as the crop boundary if the second index was selected for the MainUI combobox if (uiForm.viewsCEPRCropMethodComboBox.SelectedIndex == 1) { try { //Create some CurveLoop lists to use later IList <CurveLoop> westCurveLoopsRectangular = null; IList <CurveLoop> northCurveLoopsRectangular = null; IList <CurveLoop> southCurveLoopsRectangular = null; IList <CurveLoop> eastCurveLoopsRectangular = null; //To get a rectangular cross section of a non-rectangular room cross section, we need to generate a bounding box for the room, then make a solid from the bounding box //Get the bounding box of the room BoundingBoxXYZ roomBBox = roomSolid.GetBoundingBox(); //Use the minimum and maximum points of the bounding box to get the 4 points along the bottom of the bounding box XYZ pt0 = new XYZ(roomBBox.Min.X, roomBBox.Min.Y, roomBBox.Min.Z); XYZ pt1 = new XYZ(roomBBox.Max.X, roomBBox.Min.Y, roomBBox.Min.Z); XYZ pt2 = new XYZ(roomBBox.Max.X, roomBBox.Max.Y, roomBBox.Min.Z); XYZ pt3 = new XYZ(roomBBox.Min.X, roomBBox.Max.Y, roomBBox.Min.Z); //Generate perimeter lines for the bottom of the bounding box points Line edge0 = Line.CreateBound(pt0, pt1); Line edge1 = Line.CreateBound(pt1, pt2); Line edge2 = Line.CreateBound(pt2, pt3); Line edge3 = Line.CreateBound(pt3, pt0); //Make a list of curves out of the edges List <Curve> edges = new List <Curve>(); edges.Add(edge0); edges.Add(edge1); edges.Add(edge2); edges.Add(edge3); //Use the curves to make a CurveLoop list List <CurveLoop> loops = new List <CurveLoop>(); loops.Add(CurveLoop.Create(edges)); //Generate a solid from an extrusion that uses the CurveLoops extruded upward a height equal to the the height of the bounding box Solid initialSolidBBox = GeometryCreationUtilities.CreateExtrusionGeometry(loops, XYZ.BasisZ, (roomBBox.Max.Z - roomBBox.Min.Z)); //Create a transformed solid box from the previously created box moved to where the room bounding box is located Solid roomSolidBBox = SolidUtils.CreateTransformed(initialSolidBBox, roomBBox.Transform); //Cut the solid box with the west plane created earlier and get the faces Solid westBooleanSolidBBox = BooleanOperationsUtils.CutWithHalfSpace(roomSolidBBox, westPlane); FaceArray westBoolSolidFacesBBox = westBooleanSolidBBox.Faces; foreach (PlanarFace westFace in westBoolSolidFacesBBox) { //As with the earlier code for a fitted crop, get the face with a positive X normal XYZ westFaceNormal = westFace.FaceNormal; if (westFaceNormal.X == 1) { //Obtain the edges of the face westCurveLoopsRectangular = westFace.GetEdgesAsCurveLoops(); break; } } //Repeat for the north face Solid northBooleanSolidBBox = BooleanOperationsUtils.CutWithHalfSpace(roomSolidBBox, northPlane); FaceArray northBoolSolidFacesBBox = northBooleanSolidBBox.Faces; foreach (PlanarFace northFace in northBoolSolidFacesBBox) { XYZ northFaceNormal = northFace.FaceNormal; if (northFaceNormal.Y == -1) { northCurveLoopsRectangular = northFace.GetEdgesAsCurveLoops(); break; } } //Repeat for the east face Solid eastBooleanSolidBBox = BooleanOperationsUtils.CutWithHalfSpace(roomSolidBBox, eastPlane); FaceArray eastBoolSolidFacesBBox = eastBooleanSolidBBox.Faces; foreach (PlanarFace eastFace in eastBoolSolidFacesBBox) { XYZ eastFaceNormal = eastFace.FaceNormal; if (eastFaceNormal.X == -1) { eastCurveLoopsRectangular = eastFace.GetEdgesAsCurveLoops(); break; } } //Repeat for the south face Solid southBooleanSolidBBox = BooleanOperationsUtils.CutWithHalfSpace(roomSolidBBox, southPlane); FaceArray southBoolSolidFacesBBox = southBooleanSolidBBox.Faces; foreach (PlanarFace southFace in southBoolSolidFacesBBox) { XYZ southFaceNormal = southFace.FaceNormal; if (southFaceNormal.Y == 1) { southCurveLoopsRectangular = southFace.GetEdgesAsCurveLoops(); break; } } //As before, get the offset curve from the original curve, but offset by 1' CurveLoop offsetWestCurveLoopRectangular = CurveLoop.CreateViaOffset(westCurveLoopsRectangular[0], 1, XYZ.BasisX); ViewCropRegionShapeManager westCropRegionShapeManager = view0.GetCropRegionShapeManager(); westCropRegionShapeManager.SetCropShape(offsetWestCurveLoopRectangular); //As with the fitted offset curve, the offset for a curve in a plane with a negative vector must also be negative CurveLoop offsetNorthCurveLoopRectangular = CurveLoop.CreateViaOffset(northCurveLoopsRectangular[0], -1, XYZ.BasisY); ViewCropRegionShapeManager northCropRegionShapeManager = view1.GetCropRegionShapeManager(); northCropRegionShapeManager.SetCropShape(offsetNorthCurveLoopRectangular); CurveLoop offsetEastCurveLoopRectangular = CurveLoop.CreateViaOffset(eastCurveLoopsRectangular[0], -1, XYZ.BasisX); ViewCropRegionShapeManager eastCropRegionShapeManager = view2.GetCropRegionShapeManager(); eastCropRegionShapeManager.SetCropShape(offsetEastCurveLoopRectangular); CurveLoop offsetSouthCurveLoopRectangular = CurveLoop.CreateViaOffset(southCurveLoopsRectangular[0], 1, XYZ.BasisY); ViewCropRegionShapeManager southCropRegionShapeManager = view3.GetCropRegionShapeManager(); southCropRegionShapeManager.SetCropShape(offsetSouthCurveLoopRectangular); } catch (Exception e) { MessageBox.Show(e.ToString()); } } //If the user opted to override the crop boundary of the elevations, continue as follows if (uiForm.viewsCEPROverrideCheckBox.Checked == true) { //Make a new OverrideGraphicsSetting to use in the boundary override OverrideGraphicSettings orgs = new OverrideGraphicSettings(); //Use the solid line pattern orgs.SetProjectionLinePatternId(LinePatternElement.GetSolidPatternId()); //Set the line weight to the properties value orgs.SetProjectionLineWeight(Properties.Settings.Default.RevitOverrideInteriorCropWeight); //Grab all of the viewers, which are the viewport windows, and cycle through them var viewers = new FilteredElementCollector(uidoc.Document).OfCategory(BuiltInCategory.OST_Viewers); foreach (Element viewer in viewers) { //Get the parameters for the viewer ParameterSet parameters = viewer.Parameters; foreach (Parameter parameter in parameters) { //Get the View Name parameter if (parameter.Definition.Name.ToString() == "View Name") { string viewName = parameter.AsString(); //If the view's view name is the same as the west elvation, continue if (viewName == view0.Name) { //Set the view's override setting using the viewer and the OverrideGraphicsSettings Autodesk.Revit.DB.View viewtouse = view0 as Autodesk.Revit.DB.View; viewtouse.SetElementOverrides(viewer.Id, orgs); } //Continue to evaluate for the other view names else if (viewName == view1.Name) { Autodesk.Revit.DB.View viewtouse = view1 as Autodesk.Revit.DB.View; viewtouse.SetElementOverrides(viewer.Id, orgs); } else if (viewName == view2.Name) { Autodesk.Revit.DB.View viewtouse = view2 as Autodesk.Revit.DB.View; viewtouse.SetElementOverrides(viewer.Id, orgs); } else if (viewName == view3.Name) { Autodesk.Revit.DB.View viewtouse = view3 as Autodesk.Revit.DB.View; viewtouse.SetElementOverrides(viewer.Id, orgs); } else { //If the view's name is not one of the create elevation views, skip it continue; } } } } } } t1.Commit(); } catch (Exception e) { MessageBox.Show(e.ToString()); t1.RollBack(); } t1.Dispose(); } } catch { //If the user did not select any room tags or room elements, then report that MessageBox.Show("No rooms were selected"); } } } else if (uidoc.ActiveView.GetType().ToString() != "Autodesk.Revit.DB.ViewPlan") { //If the user tried to run this outside a plan view, report it MessageBox.Show("Please run from a plan view"); } else { //If the user did not select an elevation type, report it MessageBox.Show("No elevation type selected"); } }
public ViewCropRegionShapeManagerGetSplitRegionOffsets(string label, ViewCropRegionShapeManager viewCropRegionShapeManager) : base(label) { _viewCropRegionShapeManager = viewCropRegionShapeManager; }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; SpatialElementBoundaryOptions seb_opt = new SpatialElementBoundaryOptions(); FilteredElementCollector levels = new FilteredElementCollector(doc) .OfClass(typeof(Level)); using (Transaction tx = new Transaction(doc)) { tx.Start("Create cropped views for each room"); string date_iso = DateTime.Now.ToString("yyyy-MM-dd"); foreach (Level level in levels) { Debug.Print(level.Name); ElementId id_view = level.FindAssociatedPlanViewId(); ViewPlan view = doc.GetElement(id_view) as ViewPlan; IEnumerable <Room> rooms = new FilteredElementCollector(doc, id_view) .OfClass(typeof(SpatialElement)) .Where <Element>(e => e is Room) .Cast <Room>(); foreach (Room room in rooms) { string view_name = string.Format( "{0}_cropped_to_room_{1}_date_{2}", view.Name, room.Name, date_iso); id_view = view.Duplicate( ViewDuplicateOption.AsDependent); View view_cropped = doc.GetElement(id_view) as View; view_cropped.Name = view_name; IList <IList <BoundarySegment> > sloops = room.GetBoundarySegments(seb_opt); if (null == sloops) // the room may not be bound { continue; } CurveLoop loop = null; foreach (IList <BoundarySegment> sloop in sloops) { loop = new CurveLoop(); foreach (BoundarySegment s in sloop) { loop.Append(s.GetCurve()); } // Skip out after first sloop - ignore // rooms with holes and disjunct parts break; } ViewCropRegionShapeManager vcrs_mgr = view_cropped.GetCropRegionShapeManager(); bool valid = vcrs_mgr .IsCropRegionShapeValid(loop); //loop = cre if (valid) { view_cropped.CropBoxVisible = true; view_cropped.CropBoxActive = true; vcrs_mgr.SetCropShape(loop); } } } tx.Commit(); } return(Result.Succeeded); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { //Goal: convert the Viewport centre coordinates on a Sheet to Project Base Point (and then Survey Point) coordinates. //Solution: Find the Viewport's view centre point which is in PBP coordinates. //Problem: the Vieport centre does not always match the View centre. Annotations, Matchlines and Grids can affect the extent of the viewport. //Solution: hide all these categories and find the Viewport centre that matches the View centre. Then find the View centre point in PBP coordinates and translate it //by the vector from Viewport original centre and the centre of the Viewport with the categories hidden. //https://thebuildingcoder.typepad.com/blog/2018/03/boston-forge-accelerator-and-aligning-plan-views.html UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; StringBuilder sb = new StringBuilder(); sb.AppendLine($"Sheet Number,View Centre WCS-X,View Centre WCS-Y,View Centre WCS-Z,Angle to North,Viewport Centre-X,Viewport Centre-Y,Viewport Centre-Z,Viewport Width,Viewport Height,Xref name,Group"); string outputFile = "summary.csv"; ProjectLocation pl = doc.ActiveProjectLocation; Transform ttr = pl.GetTotalTransform().Inverse; ProjectPosition projPosition = doc.ActiveProjectLocation.GetProjectPosition(new XYZ(0, 0, 0)); //rotation IEnumerable <ViewSheet> allSheets = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Sheets) .WhereElementIsNotElementType().ToElements().Cast <ViewSheet>(); IList <string> dWGExportOptions = DWGExportOptions.GetPredefinedSetupNames(doc); //List<ViewScheduleOption> viewScheduleOptions = Helpers.GetViewScheduleOptions(doc); //find all the sheet list List <ViewSchedule> viewSchedule = Helpers.SheetList(doc); int counter = 0; try { using (var form = new Form1()) { form.CboxExportSettingsDataSource = dWGExportOptions; //set the form sheets form.CboxSheetDataSource = viewSchedule; //set the form title form.Text = "Mx CADD Export Xrefs"; //use ShowDialog to show the form as a modal dialog box. form.ShowDialog(); //if the user hits cancel just drop out of macro if (form.DialogResult == winForm.DialogResult.Cancel) { return(Result.Cancelled); } string destinationFolder = form.TBoxDestinationFolder; //string[] sheetNumbers = form.tboxSelectedSheets.Split(' '); //selected Sheet List ViewSchedule selectedSheetList = form.selectedViewSchedule; //Sheets in selected sheet list var selectedSheets = new FilteredElementCollector(doc, selectedSheetList.Id).OfClass(typeof(ViewSheet)).ToElements().Cast <ViewSheet>(); string exportSettings = form.TBoxExportSettings; int n = selectedSheets.Count(); string s = "{0} of " + n.ToString() + " plans exported..."; string caption = "Export xrefs"; string sheetWithoutArchOrEngViewports = ""; var watch = System.Diagnostics.Stopwatch.StartNew(); using (ProgressForm pf = new ProgressForm(caption, s, n)) { foreach (ViewSheet vs in selectedSheets) { if (pf.abortFlag) { break; } try { //Collect all the viewports on the sheet ICollection <ElementId> viewportIds = vs.GetAllViewports(); //Collect all views on the sheet ISet <ElementId> placedViewsIds = vs.GetAllPlacedViews(); //Filter the views that are plans (Floor,Ceiling,Engineering or Area) and exclude Keyplans. I need the //viewport associate with the view so I cannot reuse this filter List <View> planViews = Helpers.FilterPlanViewport(doc, placedViewsIds); //Collect the viewports that shows a Floor Plan (Architecture) or Structural Plan (Engineering). Dictionary <Viewport, View> viewportViewDict = new Dictionary <Viewport, View>(); //if the sheet does not contain FloorPlan, EngineeringPlan or CeilingPlan, do not export it int hasArchOrStrViewports = 0; foreach (ElementId eid in viewportIds) { Viewport vport = doc.GetElement(eid) as Viewport; View planView = doc.GetElement(vport.ViewId) as View; //Filter the views that are plans (Floor,Ceiling,Engineering or Area) if (planView.ViewType == ViewType.FloorPlan || planView.ViewType == ViewType.EngineeringPlan || planView.ViewType == ViewType.CeilingPlan || planView.ViewType == ViewType.AreaPlan) { //if planview is not a keyplan do not export it if (Helpers.IsNotKeyplan(planView)) { viewportViewDict.Add(vport, planView); //vpPlan.Add(planView); hasArchOrStrViewports += 1; } } } if (hasArchOrStrViewports != 0) { //if the parameter does not exists use the SheetNumber string CAADparameter = vs.LookupParameter("CADD File Name").AsString() ?? vs.SheetNumber; //remove white spaces from the name string fileName = Helpers.RemoveWhitespace(CAADparameter); foreach (Viewport vp in viewportViewDict.Keys) { View vpPlan = viewportViewDict[vp]; //Get the current Viewport Centre for Autocad Viewport XYZ unchangedVPcenter = vp.GetBoxCenter(); //Set its Z value to 0 XYZ flattenVPcenter = new XYZ(unchangedVPcenter.X, unchangedVPcenter.Y, 0); //The current Viewport Centre does not match the view center. Hide all the elements in the view and set the annotation crop to the minimum (3mm). Now the //Viewport centre will match the View centre. We can then use the unchangedCenter to changedCenter vector to move the view centerpoint to the original //viewport centre. //Instead of hiding categories, we can isolate an empty one. Check that this category (OST_Loads) exists in the model or it will throw an error ICollection <ElementId> categoryToIsolate = new List <ElementId>(); Categories groups = doc.Settings.Categories; categoryToIsolate.Add(groups.get_Item(BuiltInCategory.OST_Loads).Id); //This is the new Viewport centre, aligned with the View centre XYZ changedVPcenter = null; // This is the View centre XYZ centroid = null; double scale = 304.8; using (Transaction t = new Transaction(doc, "Hide categories")) { t.Start(); vpPlan.IsolateCategoriesTemporary(categoryToIsolate); //Use the annotation crop region to find the view centroid ViewCropRegionShapeManager vcr = vpPlan.GetCropRegionShapeManager(); //Set the annotation offset to the minimum (3mm) vcr.BottomAnnotationCropOffset = 3 / scale; vcr.TopAnnotationCropOffset = 3 / scale; vcr.LeftAnnotationCropOffset = 3 / scale; vcr.RightAnnotationCropOffset = 3 / scale; //Get the Viewport Center. This will match the View centroid changedVPcenter = vp.GetBoxCenter(); //Find the view centroid using the annotation crop shape (it should always be a rectangle, while the cropbox shape can be a polygon). CurveLoop cloop = vcr.GetAnnotationCropShape(); List <XYZ> pts = new List <XYZ>(); foreach (Curve crv in cloop) { pts.Add(crv.GetEndPoint(0)); pts.Add(crv.GetEndPoint(1)); } //View centroid with elements hidden centroid = Helpers.GetCentroid(pts, pts.Count); t.RollBack(); } //Set ChangedVP center Z value to 0 XYZ flattenChangedVPcenter = new XYZ(changedVPcenter.X, changedVPcenter.Y, 0); //This is the vector from the Viewport original centre to Viewport centre with all the elements hidden and the cropbox set to 3mm evenly XYZ viewPointsVector = (flattenVPcenter - flattenChangedVPcenter) * vpPlan.Scale; //View center adjusted to Viewport original centre (the one to be used in Autocad) XYZ translatedCentroid = centroid + viewPointsVector; //View center per Survey Point coordinates XYZ viewCentreWCS = ttr.OfPoint(translatedCentroid); XYZ viewCentreWCSZ = new XYZ(viewCentreWCS.X, viewCentreWCS.Y, vpPlan.get_BoundingBox(vpPlan).Transform.Origin.Z); //Viewport outline width and height to be used to update the autocad viewport XYZ maxPt = vp.GetBoxOutline().MaximumPoint; XYZ minPt = vp.GetBoxOutline().MinimumPoint; int width = Convert.ToInt32((maxPt.X - minPt.X) * 304.8); int height = Convert.ToInt32((maxPt.Y - minPt.Y) * 304.8); //string xrefName = $"{vs.SheetNumber}-{vp.Id}-xref"; //Set the file name to CAAD parameter string xrefName = $"{fileName}-{vp.Id}-xref"; if (!Helpers.ExportDWG(doc, vpPlan, exportSettings, xrefName, destinationFolder)) { TaskDialog.Show("Error", "Check that the destination folder exists"); } else { counter += 1; } //Check if views are overlapping. If they are, xref should not be bind string group = ""; // TBC dictionary values are working. Seems to work more accurately than planViews. TBC2 they seem to // give the same output //if (Helpers.CheckSingleViewOverlaps(doc, vpPlan, planViews)) if (Helpers.CheckSingleViewOverlaps(doc, vpPlan, viewportViewDict.Values.ToList())) { group = "xref"; } else { group = "bind"; } sb.AppendLine($"{ fileName}," + $"{ Helpers.PointToString(viewCentreWCSZ)}," + $"{projPosition.Angle * 180 / Math.PI}," + $"{Helpers.PointToString(flattenVPcenter)}," + $"{width.ToString()},{height.ToString()}," + $"{xrefName}," + $"{group}"); } //close foreach } //close if sheet has viewports to export else { sheetWithoutArchOrEngViewports += $"{vs.SheetNumber}\n"; } pf.Increment(); } catch (Exception ex) { sheetWithoutArchOrEngViewports += $"{vs.SheetNumber}: {ex.Message}\n"; //TaskDialog.Show("r", vs.SheetNumber); } } File.WriteAllText($"{destinationFolder}\\{outputFile}", sb.ToString()); }//close form watch.Stop(); var elapsedMinutes = watch.ElapsedMilliseconds / 1000 / 60; TaskDialog.Show("Done", $"{counter} plans have been exported and the csv has been created in {elapsedMinutes} min.\nNot exported:\n{sheetWithoutArchOrEngViewports}"); return(Result.Succeeded); }//close form } catch (Exception ex) { TaskDialog.Show("Error", ex.Message); return(Result.Failed); } }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; ICollection <ElementId> selectedElementsId = uidoc.Selection.GetElementIds(); List <View> selectedViews = new List <View>(); foreach (ElementId eid in selectedElementsId) { View current = doc.GetElement(eid) as View; selectedViews.Add(current); } int count = 0; string error = ""; var form = new Forms.FormPickFromDropDown(); using (Transaction t = new Transaction(doc, "Resize viewport")) { if (selectedViews.Count > 1) { form.ViewSectionList = new ObservableCollection <View>(selectedViews.OrderBy(x => x.Name)); form.ShowDialog(); } else { TaskDialog.Show("Error", "Please select some Section Views first."); return(Result.Cancelled); } if (form.DialogResult == false) { return(Result.Cancelled); } View sourceView = form.SelectedViewSection; BoundingBoxXYZ sourceViewBB = sourceView.CropBox; ViewCropRegionShapeManager vcrSource = sourceView.GetCropRegionShapeManager(); CurveLoop sourceLoop = vcrSource.GetCropShape()[0]; t.Start(); foreach (ElementId eid in selectedElementsId) { View destinationView = doc.GetElement(eid) as View; try { //The origin of the cropbox (from Transform) is not the same for different Sections. Use CropRegionShapeManager instead //destinationView.CropBox.Transform.Origin = sourceViewBB.Transform.Origin; //destinationView.CropBox = sourceViewBB; ViewCropRegionShapeManager destinationVcr = destinationView.GetCropRegionShapeManager(); destinationVcr.SetCropShape(sourceLoop); //if the crop is rectangular if (sourceLoop.Count() == 4) { destinationVcr.RemoveCropRegionShape(); //Reset Crop after it has been set } count++; } catch { error += $"Error processing view: {destinationView.Name}\n"; } } t.Commit(); } TaskDialog.Show("Result", $"{count}/{selectedElementsId.Count} viewport updated. \n{error}"); return(Result.Succeeded); }
/// <summary> /// 在房间X的中心创建四个方向的立面 /// Create four Elevations on the center of the "X" of the selRoom /// </summary> /// <param name="elevationOffset"></param> /// <param name="FloorThickness"></param> public void CreateElevations(double elevationOffset, double FloorThickness) { int i = 0;//循环用 //获取立面的familytype Get the familyType of Elevation FilteredElementCollector collector = new FilteredElementCollector(DocSet.doc); collector.OfClass(typeof(ViewFamilyType)); var viewFamilyTypes = from elem in collector let type = elem as ViewFamilyType where type.ViewFamily == ViewFamily.Elevation select type; ElementId viewTypeId; if (viewFamilyTypes.Count() > 0) { viewTypeId = viewFamilyTypes.First().Id; } else { return; } using (Transaction tran = new Transaction(DocSet.doc)) { //房间的"X"的交点 LocationPoint pt = DocSet.selRoom.Location as LocationPoint; tran.Start("newElvation"); ElevationMarker marker = ElevationMarker.CreateElevationMarker(DocSet.doc, viewTypeId, pt.Point, 50); for (; i < 4; i++) { ViewSection sv = marker.CreateElevation(DocSet.doc, DocSet.doc.ActiveView.Id, i); //设定立面的 远剪裁偏移 sv.get_Parameter(BuiltInParameter.VIEWER_BOUND_OFFSET_FAR).SetValueString("10000"); //设定每个立面的名称 XYZ normal = null;//法向量 string elevationName = "ELE -"; switch (i) { case 0: elevationName += " West " + _SoANumber; normal = new XYZ(-1, 0, 0); sv.get_Parameter(BuiltInParameter.VIEW_DESCRIPTION).Set("ELEVATION WEST"); break; case 1: elevationName += " North" + _SoANumber; normal = new XYZ(0, 1, 0); sv.get_Parameter(BuiltInParameter.VIEW_DESCRIPTION).Set("ELEVATION NORTH"); break; case 2: elevationName += " East" + _SoANumber; normal = new XYZ(1, 0, 0); sv.get_Parameter(BuiltInParameter.VIEW_DESCRIPTION).Set("ELEVATION EAST"); break; case 3: elevationName += " South" + _SoANumber; normal = new XYZ(0, -1, 0); sv.get_Parameter(BuiltInParameter.VIEW_DESCRIPTION).Set("ELEVATION SOUTH"); break; } sv.ViewName = elevationName; //不能删 必须先保存修改才能获取上面的元素 tran.Commit(); tran.Start("change elevation crop shape"); //小指型房间专用修改 if (cbSpRoom.IsChecked == true) { if (i == 1 || i == 2) { normal = -normal; } spRoomElevationChange(sv, elevationOffset, normal, FloorThickness); } else { //修改立面底边的高度 XYZ pt1 = null; XYZ pt2 = null; XYZ pt3 = null; XYZ pt4 = null; sv.CropBoxActive = true; ViewCropRegionShapeManager vcrShanpMgr = sv.GetCropRegionShapeManager(); CurveLoop loop = vcrShanpMgr.GetCropShape().First(); CurveLoopIterator iterator = loop.GetCurveLoopIterator(); //分辨点的位置 while (iterator.MoveNext()) { Curve curve = iterator.Current; XYZ pt0 = curve.GetEndPoint(0); if (-1 < pt0.Z - pt.Point.Z && pt0.Z - pt.Point.Z < 1) { if (pt1 == null) { pt1 = pt0; } else { pt2 = pt0; } } else { if (pt3 == null) { pt3 = pt0; } else { pt4 = pt0; } } } //重新生成一个边界框 //TaskDialog.Show("1", pt1.ToString() + "\n" + pt2.ToString() + "\n" + pt3.ToString() + "\n" + pt4.ToString()); pt1 = new XYZ(pt1.X, pt1.Y, pt1.Z + FloorThickness / 300); pt2 = new XYZ(pt2.X, pt2.Y, pt1.Z); Line lineBottom = Line.CreateBound(pt1, pt2); Line lineRight = Line.CreateBound(pt2, pt4); Line lineTop = Line.CreateBound(pt4, pt3); Line lineLeft = Line.CreateBound(pt3, pt1); CurveLoop profile = new CurveLoop(); profile.Append(lineBottom); profile.Append(lineRight); profile.Append(lineTop); profile.Append(lineLeft); profile = CurveLoop.CreateViaOffset(profile, elevationOffset / 300, -normal); vcrShanpMgr.SetCropShape(profile); } } tran.Commit(); } }