예제 #1
0
        /// <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());
            }
        }
예제 #2
0
        /// <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();
            }
        }
예제 #3
0
        /// <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());
            }
        }
예제 #4
0
        /// <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();
            }
        }
예제 #5
0
        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);
            }
        }
예제 #6
0
        /// <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();
            }
        }