/// <summary> /// Normalizes all points in the selected subregion to the average elevation of the host surface. /// </summary> /// <param name="uiDoc">The document.</param> private void NormalizeSubregionAndPoints(UIDocument uiDoc) { Document doc = uiDoc.Document; // Pick subregion TopographySurface subregion = SiteUIUtils.PickSubregion(uiDoc); TopographySurface toposurface = SiteEditingUtils.GetTopographySurfaceHost(subregion); IList <XYZ> points = SiteEditingUtils.GetPointsFromSubregionExact(subregion); // Get elevation of all points on the toposurface IList <XYZ> allPoints = toposurface.GetPoints(); double elevation = SiteEditingUtils.GetAverageElevation(allPoints); // Edit scope for all changes using (TopographyEditScope editScope = new TopographyEditScope(doc, "Edit TS")) { editScope.Start(toposurface.Id); using (Transaction t = new Transaction(doc, "Normalize terrain")) { t.Start(); // Change all points to same elevation toposurface.ChangePointsElevation(points, elevation); t.Commit(); } editScope.Commit(new TopographyEditFailuresPreprocessor()); } }
/// <summary> /// Deletes a subregion and all topography surface points it contains. /// </summary> /// <param name="uiDoc">The document.</param> public void DeleteSubregionAndPoints(UIDocument uiDoc) { Document doc = uiDoc.Document; // Select subregion TopographySurface subregion = SiteUIUtils.PickSubregion(uiDoc); TopographySurface toposurface = SiteEditingUtils.GetTopographySurfaceHost(subregion); IList <XYZ> points = SiteEditingUtils.GetNonBoundaryPoints(subregion); // All changes are added to one transaction group - will create one undo item using (TransactionGroup deleteGroup = new TransactionGroup(doc, "Delete region")) { deleteGroup.Start(); // Edit scope to delete points- if there are points in the region if (points.Count > 0) { using (TopographyEditScope editScope = new TopographyEditScope(doc, "Edit TS")) { editScope.Start(toposurface.Id); // Transaction for point deletion using (Transaction t = new Transaction(doc, "Delete points")) { t.Start(); toposurface.DeletePoints(points); t.Commit(); } editScope.Commit(new TopographyEditFailuresPreprocessor()); } } // Transaction to delete subregion using (Transaction t2 = new Transaction(doc, "Delete subregion")) { t2.Start(); doc.Delete(subregion.Id); t2.Commit(); } deleteGroup.Assimilate(); } }
/// <summary> /// Changes the elevation of all points in the subregion by a designated delta. /// </summary> /// <param name="uiDoc">The document.</param> /// <param name="elevationDelta">The change in elevation.</param> public static void ChangeSubregionAndPointsElevation(UIDocument uiDoc, double elevationDelta) { Document doc = uiDoc.Document; // Pick subregion TopographySurface subregion = PickSubregion(uiDoc); TopographySurface toposurface = SiteEditingUtils.GetTopographySurfaceHost(subregion); // Get points IList <XYZ> points = SiteEditingUtils.GetNonBoundaryPoints(subregion); if (points.Count == 0) { return; } // Change in elevation XYZ delta = elevationDelta * XYZ.BasisZ; // Edit scope for all changes using (TopographyEditScope editScope = new TopographyEditScope(doc, "Raise/lower terrain")) { editScope.Start(toposurface.Id); using (Transaction t = new Transaction(doc, "Raise/lower terrain")) { t.Start(); // Use MovePoints to change all points relative to their current position toposurface.MovePoints(points, delta); t.Commit(); } editScope.Commit(new TopographyEditFailuresPreprocessor()); } }
/// <summary> /// Adds a new retaining pond. /// </summary> /// <param name="uiDoc">The document.</param> /// <param name="pondRadius">The radius of the pond.</param> private void AddNewRetainingPond(UIDocument uiDoc, double pondRadius) { Document doc = uiDoc.Document; // Find toposurfaces FilteredElementCollector tsCollector = new FilteredElementCollector(doc); tsCollector.OfClass(typeof(TopographySurface)); IEnumerable <TopographySurface> tsEnumerable = tsCollector.Cast <TopographySurface>().Where <TopographySurface>(ts => !ts.IsSiteSubRegion); int count = tsEnumerable.Count <TopographySurface>(); // If there is only on surface, use it. If there is more than one, let the user select the target. TopographySurface targetSurface = null; if (count > 1) // tmp { targetSurface = SiteUIUtils.PickTopographySurface(uiDoc); } else { targetSurface = tsEnumerable.First <TopographySurface>(); } // Pick point and project to plane at toposurface average elevation XYZ point = SiteUIUtils.PickPointNearToposurface(uiDoc, targetSurface, "Pick point for center of pond."); double elevation = point.Z; // Add subregion first, so that any previously existing points can be removed to avoid distorting the new region // Find material "Water" FilteredElementCollector collector = new FilteredElementCollector(doc); collector.OfClass(typeof(Material)); Material mat = collector.Cast <Material>().FirstOrDefault <Material>(m => m.Name == "Water"); // Create subregion curves List <Curve> curves = new List <Curve>(); curves.Add(Arc.Create(point, pondRadius, 0, Math.PI, XYZ.BasisX, XYZ.BasisY)); curves.Add(Arc.Create(point, pondRadius, Math.PI, 2 * Math.PI, XYZ.BasisX, XYZ.BasisY)); CurveLoop curveLoop = CurveLoop.Create(curves); List <CurveLoop> curveLoops = new List <CurveLoop>(); curveLoops.Add(curveLoop); // All changes are added to one transaction group - will create one undo item using (TransactionGroup addGroup = new TransactionGroup(doc, "Add pond group")) { addGroup.Start(); IList <XYZ> existingPoints = null; // Transacton for adding subregion. using (Transaction t2 = new Transaction(doc, "Add subregion")) { t2.Start(); SiteSubRegion region = SiteSubRegion.Create(doc, curveLoops, targetSurface.Id); if (mat != null) { region.TopographySurface.MaterialId = mat.Id; } t2.Commit(); // The boundary points for the subregion cannot be deleted, since they are generated // to represent the subregion boundary rather than representing real points in the host. // Get non-boundary points only to be deleted. existingPoints = SiteEditingUtils.GetNonBoundaryPoints(region.TopographySurface); // Average elevation of all points in the subregion to use as base elevation for the pond topography elevation = SiteEditingUtils.GetAverageElevation(region.TopographySurface.GetPoints()); } // Add the topography points to the target surface via edit scope. using (TopographyEditScope editScope = new TopographyEditScope(doc, "Edit TS")) { editScope.Start(targetSurface.Id); // Transaction for points changes using (Transaction t = new Transaction(doc, "Add points")) { t.Start(); // Delete existing points first to avoid conflict if (existingPoints.Count > 0) { targetSurface.DeletePoints(existingPoints); } // Generate list of points to add IList <XYZ> points = SiteEditingUtils.GeneratePondPointsSurrounding(new XYZ(point.X, point.Y, elevation - 3), pondRadius); targetSurface.AddPoints(points); t.Commit(); } editScope.Commit(new TopographyEditFailuresPreprocessor()); } addGroup.Assimilate(); } }
private Result SlopeSelectedBuildingPad(UIDocument targetUIdoc, ref string message, double maxPointDistInFeet, double targetAngleInRadians) { Document doc = targetUIdoc.Document; Selection sel = targetUIdoc.Selection; View3D current3dView = doc.ActiveView as View3D; if (current3dView == null) { message = Properties.Messages.SlopeGradingFromPads_Not3DView; return(Result.Failed); } BuildingPad selectedBuildingPad = doc.GetElement(sel.PickObject(ObjectType.Element, new PadSelectionFilter(), Properties.Messages.SlopeGradingFromPads_SelectPad)) as BuildingPad; //Check if the Pad is associate with a Surface (never seen one doesnt, but anyways) ElementId topoElementID = selectedBuildingPad.HostId; if (topoElementID.Equals(ElementId.InvalidElementId)) { message = Properties.Messages.SlopeGradingFromPads_NoTopoAssociate; return(Result.Failed); } TopographySurface currentTopo = doc.GetElement(topoElementID) as TopographySurface; if (currentTopo == null) { message = Properties.Messages.SlopeGradingFromPads_NoTopoAssociate;; return(Result.Failed); } IList <CurveLoop> PadBoundaryLoops = new List <CurveLoop>(); CurveLoop outerLoop = null; IList <Reference> TopFacesReferences = HostObjectUtils.GetTopFaces(selectedBuildingPad); if (TopFacesReferences.Count > 1) { message = Properties.Messages.SlopeGradingFromPads_PadsWithMoreThanOneUpperFace; return(Result.Failed); } XYZ plannarDirection = XYZ.BasisZ; XYZ plannarOrigin = XYZ.Zero; // interate on the only face foreach (Reference currentFaceRef in TopFacesReferences) { GeometryObject currentFaceObj = selectedBuildingPad.GetGeometryObjectFromReference(currentFaceRef); if (currentFaceObj is PlanarFace) { PlanarFace currentPlanarFace = currentFaceObj as PlanarFace; plannarDirection = currentPlanarFace.FaceNormal; plannarOrigin = currentPlanarFace.Origin; PadBoundaryLoops = currentPlanarFace.GetEdgesAsCurveLoops(); } else { message = Properties.Messages.SlopeGradingFromPads_UpperFaceNotPlanar; return(Result.Failed); } } //Sort the curves so the outer loop comes first IList <IList <CurveLoop> > curveLoopLoop = ExporterIFCUtils.SortCurveLoops(PadBoundaryLoops); if (curveLoopLoop.Count > 0) { IList <CurveLoop> firstList = curveLoopLoop.First(); if (firstList.Count > 0) { outerLoop = firstList.First(); } } if (outerLoop == null) { message = Properties.Messages.SlopeGradingFromPads_OuterLoopIssue; return(Result.Failed); } //This will be the list of elements that the ReferenceIntersector will shoot the rays //If we try to shoot the rays only in the toposurface and the it has subregions, the reference //intersection will not recognize these regions, so its necessary to shoot rays to the surface and its subregions IList <ElementId> currentSubRegionsAndSurface = currentTopo.GetHostedSubRegionIds(); currentSubRegionsAndSurface.Add(topoElementID); //Search for the max distance from the Pad to the topography //Doesnt matter if it is upwards or downwards, but we will check that, since the ray has to go to one direction //This is to estabilish what the distance will be using to create the slope to the right amount ReferenceIntersector topoRefIntersec = new ReferenceIntersector(currentSubRegionsAndSurface, FindReferenceTarget.Mesh, current3dView); double maxDist = double.NegativeInfinity; foreach (Curve currentCurve in outerLoop) { int numberOfInteractions = 0; double increaseAmount = 0; double currentParameter = 0; EstabilishInteractionPoints(currentCurve, maxPointDistInFeet, out numberOfInteractions, out increaseAmount); for (int i = 0; i < numberOfInteractions; i++) { if (i == 0) { currentParameter = 0; } else { currentParameter += increaseAmount; } XYZ currentPointToEvaluate = currentCurve.Evaluate(currentParameter, true); ReferenceWithContext currentRefContext = topoRefIntersec.FindNearest(currentPointToEvaluate, XYZ.BasisZ); if (currentRefContext == null) { currentRefContext = topoRefIntersec.FindNearest(currentPointToEvaluate, XYZ.BasisZ.Negate()); } if (currentRefContext == null) { continue; } double currentDist = currentRefContext.Proximity; if (currentDist > maxDist) { maxDist = currentDist; } } } // if we haven't changed the maxdist yet, something went wrong if (maxDist == double.NegativeInfinity) { message = Properties.Messages.SlopeGradingFromPads_NoTopoAssociate; return(Result.Failed); } //Estabilish the offset from the pad double offsetDist = maxDist / Math.Tan(targetAngleInRadians); using (TopographyEditScope topoEditGroup = new TopographyEditScope(doc, Properties.Messages.SlopeGradingFromPads_Transaction)) { topoEditGroup.Start(topoElementID); using (Transaction t = new Transaction(doc, Properties.Messages.SlopeGradingFromPads_Transaction)) { t.Start(); CurveLoop offsetLoop = null; try { offsetLoop = CurveLoop.CreateViaOffset(outerLoop, offsetDist, plannarDirection); } catch { message += Properties.Messages.SlopeGradingFromPads_OuterOffsetLoopIssue; return(Result.Failed); } #region DebugCurve Loop //Plane p = new Plane(plannarDirection, plannarOrigin); //SketchPlane sktP = SketchPlane.Create(doc, p); //foreach (Curve currentOffsetCurve in offsetLoop) //{ // doc.Create.NewModelCurve(currentOffsetCurve, sktP); //} #endregion foreach (Curve currentOffsetCurve in offsetLoop) { int numberOfInteractions = 0; double increaseAmount = 0; double currentParameter = 0; EstabilishInteractionPoints(currentOffsetCurve, maxPointDistInFeet, out numberOfInteractions, out increaseAmount); for (int i = 0; i < numberOfInteractions; i++) { if (i == 0) { currentParameter = 0; } else { currentParameter += increaseAmount; } XYZ currentPointOffset = currentOffsetCurve.Evaluate(currentParameter, true); ReferenceWithContext currentRefContext = topoRefIntersec.FindNearest(currentPointOffset, XYZ.BasisZ); if (currentRefContext == null) { currentRefContext = topoRefIntersec.FindNearest(currentPointOffset, XYZ.BasisZ.Negate()); } //if we couldn't find points upwards and downwards, the topo is near the border, so we cant add points if (currentRefContext == null) { continue; } Reference currentReference = currentRefContext.GetReference(); XYZ currentPointToAdd = currentReference.GlobalPoint; if (currentTopo.ContainsPoint(currentPointToAdd)) { continue; } IList <XYZ> ListPointToAdd = new List <XYZ>(); ListPointToAdd.Add(currentPointToAdd); currentTopo.AddPoints(ListPointToAdd); } } foreach (Curve currentCurve in outerLoop) { int numberOfInteractions = 0; double increaseAmount = 0; double currentParameter = 0; EstabilishInteractionPoints(currentCurve, maxPointDistInFeet, out numberOfInteractions, out increaseAmount); for (int i = 0; i < numberOfInteractions; i++) { if (i == 0) { currentParameter = 0; } else { currentParameter += increaseAmount; } XYZ currentPointToAdd = currentCurve.Evaluate(currentParameter, true); if (currentTopo.ContainsPoint(currentPointToAdd)) { continue; } IList <XYZ> ListPointToAdd = new List <XYZ>(); ListPointToAdd.Add(currentPointToAdd); currentTopo.AddPoints(ListPointToAdd); } } t.Commit(); } topoEditGroup.Commit(new TopographyFailurePreprocessor()); return(Result.Succeeded); } }
/// <summary> /// Moves a subregion and the associated topography to a new user-selected location. /// </summary> /// <param name="uiDoc">The document.</param> private void MoveSubregionAndPoints(UIDocument uiDoc) { Document doc = uiDoc.Document; // Pick subregion TopographySurface subregion = SiteUIUtils.PickSubregion(uiDoc); TopographySurface toposurface = SiteEditingUtils.GetTopographySurfaceHost(subregion); IList <XYZ> points = SiteEditingUtils.GetPointsFromSubregionExact(subregion); XYZ sourceLocation = SiteEditingUtils.GetCenterOf(subregion); // Pick target location XYZ targetPoint = SiteUIUtils.PickPointNearToposurface(uiDoc, toposurface, "Pick point to move to"); // Delta for the move XYZ delta = targetPoint - sourceLocation; // All changes are added to one transaction group - will create one undo item using (TransactionGroup moveGroup = new TransactionGroup(doc, "Move subregion and points")) { moveGroup.Start(); // Get elevation of region in current location IList <XYZ> existingPointsInCurrentLocation = subregion.GetPoints(); double existingElevation = SiteEditingUtils.GetAverageElevation(existingPointsInCurrentLocation); // Move subregion first - allows the command delete existing points and adjust elevation to surroundings using (Transaction t2 = new Transaction(doc, "Move subregion")) { t2.Start(); ElementTransformUtils.MoveElement(doc, subregion.Id, delta); t2.Commit(); } // The boundary points for the subregion cannot be deleted, since they are generated // to represent the subregion boundary rather than representing real points in the host. // Get non-boundary points only to be deleted. IList <XYZ> existingPointsInNewLocation = SiteEditingUtils.GetNonBoundaryPoints(subregion); // Average elevation of all points in the subregion. double newElevation = SiteEditingUtils.GetAverageElevation(subregion.GetPoints()); // Adjust delta for elevation based on calculated values delta = SiteEditingUtils.MoveXYZToElevation(delta, newElevation - existingElevation); // Edit scope for points changes using (TopographyEditScope editScope = new TopographyEditScope(doc, "Edit TS")) { editScope.Start(toposurface.Id); using (Transaction t = new Transaction(doc, "Move points")) { t.Start(); // Delete existing points from target region if (existingPointsInNewLocation.Count > 0) { toposurface.DeletePoints(existingPointsInNewLocation); } // Move points from source region toposurface.MovePoints(points, delta); t.Commit(); } editScope.Commit(new TopographyEditFailuresPreprocessor()); } moveGroup.Assimilate(); } }