/// <summary> /// 计算线面交点 /// 平行为null /// </summary> public XYZ GetConflictPoint(MEPCurve mepCurve) { var line = (MEPCurve.Location as LocationCurve).Curve as Line; var lineToAvoid = (mepCurve.Location as LocationCurve).Curve as Line; var lineDirection1 = line.Direction; var lineDirection2 = lineToAvoid.Direction; if ((Math.Abs(lineDirection1.DotProductByCoordinate(lineDirection2, VLCoordinateType.XY)) - lineDirection1.GetLengthByCoordinate(VLCoordinateType.XY) * lineDirection2.GetLengthByCoordinate(VLCoordinateType.XY)).IsMiniValue()) { return(null); } VLTriangle triangle = new VLTriangle(lineToAvoid.GetEndPoint(0), lineToAvoid.GetEndPoint(1), lineToAvoid.GetEndPoint(0) + new XYZ(0, 0, 1)); return(VLGeometryHelper.GetIntersection(triangle, line.GetEndPoint(0), line.Direction)); }
public AvoidData( //碰撞检测数据 Document document, IEnumerable <ElementId> selectedPipeIds, PipeAnnotationEntity entity, List <Line> currentLines, VLTriangle currentTriangle, FamilySymbol multipleTagSymbol, //避让数据 XYZ parallelVector, double leftSpace, double rightSpace ) { Document = document; SelectedPipeIds = selectedPipeIds; Entity = entity; CurrentLines = currentLines; CurrentTriangle = currentTriangle; MultipleTagSymbol = multipleTagSymbol; ParallelVector = parallelVector; LeftSpace = leftSpace; RightSpace = rightSpace; }
/// <summary> /// 避让测试 /// return true when collided /// return false when passed /// </summary> /// <returns></returns> public bool CheckCollision(AvoidData data, bool tryAvoid = false) { Document document = data.Document; View view = document.ActiveView; IEnumerable <ElementId> selectedPipeIds = data.SelectedPipeIds; ElementId currentLineId = new ElementId(data.Entity.LineId); List <Line> currentLines = tryAvoid ? data.TemporaryLines : data.CurrentLines; VLTriangle currentTriangle = tryAvoid ? data.TemporaryTriangle : data.CurrentTriangle; FamilySymbol multipleTagSymbol = data.MultipleTagSymbol; //管道避让 var otherPipeLines = new FilteredElementCollector(document).OfClass(typeof(Pipe)) .Select(c => Line.CreateBound((c.Location as LocationCurve).Curve.GetEndPoint(0), (c.Location as LocationCurve).Curve.GetEndPoint(1))).ToList(); var pipeCollisions = new FilteredElementCollector(document).OfClass(typeof(Pipe)).Excluding(selectedPipeIds.ToList()) .Select(c => Line.CreateBound((c.Location as LocationCurve).Curve.GetEndPoint(0), (c.Location as LocationCurve).Curve.GetEndPoint(1))).ToList() .Where(c => VLGeometryHelper.IsPlanarCover(currentLines, currentTriangle, c) != VLGeometryHelper.VLCoverType.Disjoint).ToList(); //标注避让 var collector = new FilteredElementCollector(document).OfClass(typeof(FamilyInstance)).WhereElementIsNotElementType().Excluding(new List <ElementId>() { currentLineId }); var otherLines = collector.Where(c => (c as FamilyInstance).Symbol.Id == multipleTagSymbol.Id); var boundingBoxes = otherLines.Select(c => c.get_BoundingBox(view)); List <BoundingBoxXYZ> crossedBoundingBox = new List <BoundingBoxXYZ>(); List <BoundingBoxXYZ> uncrossedBoundingBox = new List <BoundingBoxXYZ>(); foreach (var boundingBox in boundingBoxes.Where(c => c != null)) { if (VLGeometryHelper.VL_IsRectangleCrossed(currentTriangle.A, currentTriangle.C, boundingBox.Min, boundingBox.Max)) { crossedBoundingBox.Add(boundingBox); } else { uncrossedBoundingBox.Add(boundingBox); } } PmSoft.Optimization.DrawingProduction.Utils.GraphicsDisplayerManager.Display(@"E:\WorkingSpace\Outputs\Images\0822标注避让.png", tryAvoid ? data.TemporaryTriangle : data.CurrentTriangle, otherPipeLines, pipeCollisions, crossedBoundingBox, uncrossedBoundingBox); return(pipeCollisions.Count() > 0 || crossedBoundingBox.Count() > 0); }
public static void Display(string path, VLTriangle triangle, List <Line> pipeLines, List <Line> pipeCollisions, List <BoundingBoxXYZ> crossedBoundingBoxes, List <BoundingBoxXYZ> uncrossedBoundingBoxes) { if (pipeLines.Count() == 0) { return; } var uncross = new Pen(Brushes.LightGray); var cross = new Pen(Brushes.Red); var self = new Pen(Brushes.Black); var maxX = (int)pipeLines.Max(c => new XYZ[] { c.GetEndPoint(0), c.GetEndPoint(1) }.Max(b => b.X)); var minX = (int)pipeLines.Min(c => new XYZ[] { c.GetEndPoint(0), c.GetEndPoint(1) }.Min(b => b.X)); var maxY = (int)pipeLines.Max(c => new XYZ[] { c.GetEndPoint(0), c.GetEndPoint(1) }.Max(b => b.Y)); var minY = (int)pipeLines.Min(c => new XYZ[] { c.GetEndPoint(0), c.GetEndPoint(1) }.Min(b => b.Y)); var offSetX = -minX; var offSetY = -minY; var graphicsDisplayer = new GraphicsDisplayer(minX, maxX, minY, maxY); int displayLength = 10; graphicsDisplayer.DisplayLines(pipeLines.Where(c => c.Length >= displayLength).ToList(), uncross, false, true); graphicsDisplayer.DisplayLines(pipeLines.Where(c => c.Length < displayLength).ToList(), uncross, false, false); graphicsDisplayer.DisplayLines(pipeCollisions, cross, false, true); graphicsDisplayer.DisplayClosedInterval(new List <XYZ>() { triangle.A, triangle.B, triangle.C }, self, false, true); foreach (var boundingBox in crossedBoundingBoxes) { graphicsDisplayer.DisplayClosedInterval(GetPointsFromBoundingBox(boundingBox), cross, false, true); } foreach (var boundingBox in uncrossedBoundingBoxes) { graphicsDisplayer.DisplayClosedInterval(GetPointsFromBoundingBox(boundingBox), uncross, false, true); } graphicsDisplayer.SaveTo(path); }
/// <summary> /// 生成标注 /// </summary> /// <param name="selectedIds"></param> /// <param name="entity"></param> /// <param name="view"></param> /// <returns></returns> AnnotationBuildResult GenerateMultipleTagSymbol(Document document, IEnumerable <ElementId> selectedIds, PipeAnnotationEntity entity, MultiPipeAnnotationSettings setting) { View view = document.ActiveView; XYZ startPoint = null; FamilyInstance line = null; List <PipeAndNodePoint> pipeAndNodePoints = new List <PipeAndNodePoint>(); var tags = new List <IndependentTag>(); //管道 获取 foreach (var selectedId in selectedIds) { pipeAndNodePoints.Add(new PipeAndNodePoint(Document.GetElement(selectedId) as Pipe)); } //平行,垂直 向量 XYZ parallelVector = null; XYZ verticalVector = null; parallelVector = ((pipeAndNodePoints.First().Pipe.Location as LocationCurve).Curve as Line).Direction; verticalVector = new XYZ(parallelVector.Y, -parallelVector.X, 0); parallelVector = LocationHelper.GetVectorByQuadrant(parallelVector, QuadrantType.OneAndFour); verticalVector = LocationHelper.GetVectorByQuadrant(verticalVector, QuadrantType.OneAndTwo); if (parallelVector.Y == 1) { verticalVector = -verticalVector; } //平行检测 if (!CheckParallel(pipeAndNodePoints.Select(c => c.Pipe), verticalVector)) { return(AnnotationBuildResult.NotParallel); } XYZ rightOfLefts; //左侧点的右边界 XYZ leftOfRights; //右侧点的左边界 //节点计算 if (!GetNodePoints(pipeAndNodePoints, out rightOfLefts, out leftOfRights)) { return(AnnotationBuildResult.NoOverlap); } pipeAndNodePoints = pipeAndNodePoints.OrderByDescending(c => c.NodePoint.Y).ToList(); var pipes = pipeAndNodePoints.Select(c => c.Pipe).ToList(); var orderedNodePoints = pipeAndNodePoints.Select(c => c.NodePoint).ToList(); //起始点 startPoint = orderedNodePoints.First(); //线 创建 var multipleTagSymbol = PAContext.GetMultipleTagSymbol(document); if (!multipleTagSymbol.IsActive) { multipleTagSymbol.Activate(); } line = Document.Create.NewFamilyInstance(startPoint, multipleTagSymbol, view); //线 旋转处理 LocationPoint locationPoint = line.Location as LocationPoint; if (locationPoint != null) { locationPoint.RotateByXY(startPoint, verticalVector); } //线 参数设置 UpdateLineParameters(orderedNodePoints, line, verticalVector); //标注 创建 var textSize = PAContext.TextSize; var widthScale = PAContext.WidthScale; //碰撞检测区域点 XYZ avoidP1_Line1 = orderedNodePoints.Last(); XYZ avoidP2_Line2 = null; XYZ avoidP3_Annotation1 = null; switch (entity.LocationType) { case MultiPipeTagLocation.OnLineEdge: //添加对应的单管直径标注 line.GetParameters(TagProperty.线宽度.ToString()).First().Set(UnitHelper.ConvertToFoot(200, AnnotationConstaints.UnitType)); var height = Convert.ToDouble(line.GetParameters(TagProperty.线高度1.ToString()).First().AsValueString()) + (orderedNodePoints.Count() - 1) * AnnotationConstaints.TextHeight; avoidP2_Line2 = avoidP1_Line1 + UnitHelper.ConvertToFoot(height, AnnotationConstaints.UnitType) * verticalVector; var skewLength = AnnotationConstaints.SkewLengthForOffLine; for (int i = 0; i < pipes.Count(); i++) { var subTag = Document.Create.NewTag(view, pipes[i], false, TagMode.TM_ADDBY_CATEGORY, TagOrientation.Horizontal, startPoint); var text = subTag.TagText; var textLength = System.Windows.Forms.TextRenderer.MeasureText(text, AnnotationConstaints.Font).Width; var actualLength = textLength / (textSize * widthScale); subTag.TagHeadPosition = startPoint + skewLength * parallelVector + UnitHelper.ConvertToInch(actualLength, VLUnitType.millimeter) * parallelVector + UnitHelper.ConvertToFoot(height - i * AnnotationConstaints.TextHeight, AnnotationConstaints.UnitType) * verticalVector; tags.Add(subTag); if (i == 0) { avoidP3_Annotation1 = subTag.TagHeadPosition + skewLength * parallelVector + UnitHelper.ConvertToInch(actualLength, VLUnitType.millimeter) * parallelVector + UnitHelper.ConvertToFoot(0.5 * AnnotationConstaints.TextHeight, AnnotationConstaints.UnitType) * verticalVector; } } break; case MultiPipeTagLocation.OnLine: //添加对应的单管直径标注 line.GetParameters(TagProperty.线宽度.ToString()).First().Set(UnitHelper.ConvertToFoot(800, AnnotationConstaints.UnitType)); height = Convert.ToDouble(line.GetParameters(TagProperty.线高度1.ToString()).First().AsValueString()) + (orderedNodePoints.Count() - 1) * AnnotationConstaints.TextHeight; avoidP2_Line2 = avoidP1_Line1 + UnitHelper.ConvertToFoot(height, AnnotationConstaints.UnitType) * verticalVector; skewLength = AnnotationConstaints.SkewLengthForOnLine; for (int i = 0; i < pipes.Count(); i++) { var subTag = Document.Create.NewTag(view, pipes[i], false, TagMode.TM_ADDBY_CATEGORY, TagOrientation.Horizontal, startPoint); var text = subTag.TagText; var textLength = System.Windows.Forms.TextRenderer.MeasureText(text, AnnotationConstaints.Font).Width; var actualLength = textLength / (textSize * widthScale); subTag.TagHeadPosition = startPoint + skewLength * parallelVector + UnitHelper.ConvertToInch(actualLength, VLUnitType.millimeter) * parallelVector + UnitHelper.ConvertToFoot(height - i * AnnotationConstaints.TextHeight + 0.5 * AnnotationConstaints.TextHeight, AnnotationConstaints.UnitType) * verticalVector; tags.Add(subTag); if (i == 0) { avoidP3_Annotation1 = subTag.TagHeadPosition + skewLength * parallelVector + UnitHelper.ConvertToInch(actualLength, VLUnitType.millimeter) * parallelVector + UnitHelper.ConvertToFoot(AnnotationConstaints.TextHeight, AnnotationConstaints.UnitType) * verticalVector; } } break; default: return(AnnotationBuildResult.NoLocationType); } entity.ViewId = view.Id.IntegerValue; entity.LineId = line.Id.IntegerValue; foreach (var pipe in pipes) { entity.PipeIds.Add(pipe.Id.IntegerValue); } foreach (var tag in tags) { entity.TagIds.Add(tag.Id.IntegerValue); } entity.StartPoint = startPoint; //碰撞检测 VLTriangle triangle = new VLTriangle(avoidP1_Line1, avoidP2_Line2, avoidP3_Annotation1); List <Line> lines = triangle.GetLines(); AvoidData data = new AvoidData(document, selectedIds, entity, lines, triangle, multipleTagSymbol, parallelVector, rightOfLefts.GetLength(), leftOfRights.GetLength()); AvoidStrategy strategty = AvoidStrategy.MoveLeft; var strategyEntity = AvoidStrategyFactory.GetAvoidStrategyEntity(strategty); strategyEntity.Data = data; while (strategyEntity.CheckCollision(strategyEntity.Data)) { if (strategyEntity.TryAvoid()) { strategyEntity.Apply(data); break; } else { strategyEntity = strategyEntity.GetNextStratetyEntity(); } } return(AnnotationBuildResult.Success); #region old //if (CheckCollision(document, view, selectedIds, line, lines, triangle, multipleTagSymbol)) //{ // int offsetLength = 10; // XYZ offset = null; // if (rightOfLefts.GetLength() > offsetLength) // offset = parallelVector * offsetLength; // else if (leftOfRights.GetLength() > offsetLength) // offset = -parallelVector * offsetLength; // else // return AnnotationBuildResult.Success; // avoidP1_Line1 += offset; // avoidP2_Line2 += offset; // avoidP3_Annotation1 += offset; // lines = GetLines(avoidP1_Line1, avoidP2_Line2, avoidP3_Annotation1); // triangle = new Triangle(avoidP1_Line1, avoidP2_Line2, avoidP3_Annotation1); // if (!CheckCollision(document, view, selectedIds, line, lines, triangle, multipleTagSymbol)) // { // //TODO 偏移处理 // Autodesk.Revit.DB.ElementTransformUtils.MoveElement(document, new ElementId(entity.LineId), offset); // foreach (var tagId in entity.TagIds) // { // Autodesk.Revit.DB.ElementTransformUtils.MoveElement(document, new ElementId(tagId), offset); // } // } //} //return AnnotationBuildResult.Success; #endregion }