/// <summary> /// Tests if a point is within a curveloop. The point wil be projected onto the /// plane which holds the curveloop before the test is executed. /// </summary> /// <param name="point">The point to test.</param> /// <param name="curveloop">A curveloop that lies in a plane.</param> /// <returns>True, if the point was inside the curveloop after the /// point was projected onto the curveloop's plane. False, otherwise.</returns> private static bool IsPointInsideCurveLoop(XYZ point, CurveLoop curveloop) { // Starting at the point, shoot an infinite ray in one direction and count how many // times the ray intersects the edges of the curveloop. If the ray intersects // an odd number of edges, then the point was inside the curveloop. If it // intersects an even number of times, then the point was outside the curveloop. // // Note: Revit doesn't have an infinite ray class, so a very long Line is used instead. // This test can fail if the curveloop is wider than the very long line. // Calculate the plane on which the edges of the curveloop lie. Plane plane = Plane.CreateByThreePoints(curveloop.ElementAt(0).GetEndPoint(0), curveloop.ElementAt(1).GetEndPoint(0), curveloop.ElementAt(2).GetEndPoint(0)); // Project the test point on the plane. XYZ projectedPoint = ProjectPointOnPlane(plane, point); // Create a very long bounded line that starts at projectedPoint and runs // along the plane's surface. Line veryLongLine = Line.CreateBound(projectedPoint, projectedPoint + (RANDOM_X_SCALE * plane.XVec) + (RANDOM_Y_SCALE * plane.YVec)); // Count how many edges of curveloop intersect veryLongLine. int intersectionCount = 0; foreach (var edge in curveloop) { IntersectionResultArray resultArray; SetComparisonResult res = veryLongLine.Intersect(edge, out resultArray); if (SetComparisonResult.Overlap == res) { intersectionCount += resultArray.Size; } } // If the intersection count is ODD, then the point is inside the curveloop. return(1 == (intersectionCount % 2)); }
public Polygon2D GetStairAreaPolygon(UIDocument currentDocument, Stairs stair, string key) { ICollection <ElementId> allRunsIds = stair.GetStairsRuns(); ElementId currentId = allRunsIds.ElementAt(0); if (key.Equals(RevitObjectManager.BASE_LEVEL_KEY)) { foreach (ElementId currentBaseId in allRunsIds) { StairsRun currentStairsRun = currentDocument.Document.GetElement(currentBaseId) as StairsRun; StairsRun selectedStairsRun = currentDocument.Document.GetElement(currentId) as StairsRun; if (currentStairsRun.BaseElevation < selectedStairsRun.BaseElevation) { currentId = currentBaseId; } } } else if (key.Equals(RevitObjectManager.TOP_LEVEL_KEY)) { foreach (ElementId currentTopId in allRunsIds) { StairsRun currentStairsRun = currentDocument.Document.GetElement(currentTopId) as StairsRun; StairsRun selectedStairsRun = currentDocument.Document.GetElement(currentId) as StairsRun; if (currentStairsRun.TopElevation > selectedStairsRun.TopElevation) { currentId = currentTopId; } } } List <Vector2D> areaNodes = new List <Vector2D>(); StairsRun finalStairsRun = currentDocument.Document.GetElement(currentId) as StairsRun; CurveLoop stairPath = finalStairsRun.GetStairsPath(); Curve firstStairPathCurve; if (stairPath.Count() > 1) { if ((finalStairsRun.StairsRunStyle.Equals(StairsRunStyle.Winder) || finalStairsRun.StairsRunStyle.Equals(StairsRunStyle.Spiral)) && key.Equals(RevitObjectManager.TOP_LEVEL_KEY)) { firstStairPathCurve = stairPath.ElementAt(stairPath.Count() - 1); } else { firstStairPathCurve = stairPath.ElementAt(0); } } else { firstStairPathCurve = stairPath.ElementAt(0); } double stairsRunsWidth = ConvertFeetToMeters(finalStairsRun.ActualRunWidth * STAIRS_AREA_SHRINK_FACTOR); if (stairsRunsWidth < DEFAULT_AREA_RADIUS) { stairsRunsWidth = DEFAULT_AREA_RADIUS; } double pathsLength = ConvertFeetToMeters(firstStairPathCurve.Length * STAIRS_AREA_SHRINK_FACTOR); if (pathsLength < DEFAULT_AREA_RADIUS) { pathsLength = DEFAULT_AREA_RADIUS; } Vector2D pathsStart = GeometryFactory.CreateVector2D(ConvertFeetToMeters(firstStairPathCurve.GetEndPoint(0).X), ConvertFeetToMeters(firstStairPathCurve.GetEndPoint(0).Y), MEASUREMENTUNITFACTOR); Vector2D pathsEnd = GeometryFactory.CreateVector2D(ConvertFeetToMeters(firstStairPathCurve.GetEndPoint(1).X), ConvertFeetToMeters(firstStairPathCurve.GetEndPoint(1).Y), MEASUREMENTUNITFACTOR); Vector2D pathDirection = pathsEnd.Difference(pathsStart); Vector2D pathDirectionPerpenticular = pathDirection.Rotate((-1) * Math.PI / 2).GetAsNormalized(); Vector2D firstNode = pathsStart.Add(pathDirectionPerpenticular.Multiply(stairsRunsWidth / 2)); areaNodes.Add(firstNode); Vector2D pointToAdd = firstNode.Add(pathDirection); areaNodes.Add(pointToAdd); pointToAdd = pointToAdd.Add(pathDirectionPerpenticular.Multiply((-1) * stairsRunsWidth)); areaNodes.Add(pointToAdd); pointToAdd = pointToAdd.Add(pathDirection.Multiply(-1)); areaNodes.Add(pointToAdd); areaNodes.Add(firstNode); Polygon2D areaPolygon = GeometryFactory.CreatePolygon2D(areaNodes.ToArray(), finalStairsRun.Name); return(areaPolygon); }