public static ArcModelMini GetArcParametersFromThreePoints(UnitPoint startPoint, UnitPoint midPoint, UnitPoint endPoint) { ArcModelMini arcModel = new ArcModelMini(); arcModel.Clockwise = HitUtil.IsClockwiseByCross(startPoint, midPoint, endPoint); arcModel.Center = HitUtil.CenterPointFrom3Points(startPoint, midPoint, endPoint); arcModel.Radius = (float)HitUtil.Distance(arcModel.Center, startPoint); arcModel.StartAngle = (float)HitUtil.RadiansToDegrees(HitUtil.LineAngleR(arcModel.Center, startPoint, 0)); float EndAngle = (float)HitUtil.RadiansToDegrees(HitUtil.LineAngleR(arcModel.Center, endPoint, 0)); arcModel.SweepAngle = (float)HitUtil.CalAngleSweep(arcModel.StartAngle, EndAngle, arcModel.Clockwise); return(arcModel); }
private static List <BridgePoints> GetBridgeByArc(ArcBase arc, UnitPoint p1, UnitPoint p2, BridgingModel param) { List <BridgePoints> retPoints = new List <BridgePoints>(); var line = DrawingOperationHelper.GetLineEquation(p1, p2); double width = param.Width / 2; ArcModelMini arcMini = new DrawModel.ArcModelMini() { Center = arc.Center, Radius = arc.Radius, StartAngle = arc.StartAngle, EndAngle = arc.EndAngle, SweepAngle = arc.AngleSweep, Clockwise = arc.IsClockwise }; List <UnitPoint> points = DrawingOperationHelper.GetIntersectPointByLineAndCircle(line.Item1, line.Item2, line.Item3, arc.Center, arc.Radius); var hasPoints = points?.Where(p => !p.IsEmpty && (HitUtil.IsPointOnArc(p, 0.000001f, arcMini) && HitUtil.IsPointInLine(p1, p2, p, 0.000001f))).ToList(); if (hasPoints != null && hasPoints.Count > 0) { //根据宽度求点 double angle = width / arc.Radius * (arc.IsClockwise ? 1 : -1); hasPoints?.ForEach(p => { double lineAngle = HitUtil.LineAngleR(arcMini.Center, p, 0); double angle1 = lineAngle + angle; double angle2 = lineAngle - angle; UnitPoint retPoint1 = UnitPoint.Empty; UnitPoint retPoint2 = UnitPoint.Empty; if (HitUtil.IsPointInArc(HitUtil.RadiansToDegrees(angle1), arcMini.StartAngle, arcMini.EndAngle, arcMini.Clockwise)) { //第一个位置点 retPoint1 = HitUtil.PointOnCircle(arcMini.Center, arcMini.Radius, angle1); } if (HitUtil.IsPointInArc(HitUtil.RadiansToDegrees(angle2), arcMini.StartAngle, arcMini.EndAngle, arcMini.Clockwise)) { //第二个位置点 retPoint2 = HitUtil.PointOnCircle(arcMini.Center, arcMini.Radius, angle2); } BridgePoints bridges = new BridgePoints(arc, new UnitPointBulge(retPoint1), new UnitPointBulge(retPoint2), HitUtil.Distance(p1, p)); retPoints.Add(bridges); }); } return(retPoints); }
//TODO:此方法可能存在问题 public static bool IsLineOnArc(UnitPoint p1, UnitPoint p2, UnitPoint center, float radius, double startAngle, double angleSweep, bool clockwise, float thWidth) { List <UnitPoint> unitPoints = HitUtil.GetIntersectPointLineWithCircle(p1, p2, center, radius, thWidth); for (int i = 0; i < unitPoints.Count; i++) { double angle = HitUtil.LineAngleR(center, unitPoints[i], 0); angle = HitUtil.RadiansToDegrees(angle); double sweepAngle = HitUtil.CalAngleSweep(startAngle, angle, clockwise); if (Math.Abs(angleSweep) > Math.Abs(sweepAngle)) { return(true); } } return(false); }
private void CalAngleAndDirection(UnitPoint lastPoint) { double angle = HitUtil.LineAngleR(this.FirstPoint, lastPoint, 0); double angle2 = HitUtil.LineAngleR(this.FirstPoint, this.ThirdPoint, 0); this.LastPoint = this.ThirdPoint; double theta = angle2 - angle; if (theta > Math.PI) { theta -= Math.PI * 2; } else if (theta < -Math.PI) { theta += Math.PI * 2; } clockwise = theta >= 0 ? false : true; this.rotateAngle = Math.Abs(HitUtil.RadiansToDegrees(theta)); }
/// <summary> /// 圆弧到圆弧,补偿求交点 /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="p3"></param> /// <param name="indexCur"></param> /// <returns></returns> private static List <UnitPointBulge> CalCompensationsBy2Arc(UnitPointBulge p1, UnitPointBulge p2, UnitPointBulge p3, int indexCur, CompensationModel compensationParam, bool isOutside) { var retPoints = new List <UnitPointBulge>(); ArcModelMini arc1 = DrawingOperationHelper.GetArcParametersFromBulge(p1.Point, p2.Point, (float)p1.Bulge); ArcModelMini arc2 = DrawingOperationHelper.GetArcParametersFromBulge(p2.Point, p3.Point, (float)p2.Bulge); double r1 = arc1.Clockwise ? arc1.Radius - compensationParam.Size : arc1.Radius + compensationParam.Size; double r2 = arc2.Clockwise ? arc2.Radius - compensationParam.Size : arc2.Radius + compensationParam.Size; if (isOutside) { r1 = arc1.Clockwise ? arc1.Radius + compensationParam.Size : arc1.Radius - compensationParam.Size; r2 = arc2.Clockwise ? arc2.Radius + compensationParam.Size : arc2.Radius - compensationParam.Size; } UnitPoint point1 = HitUtil.GetLinePointByDistance(arc1.Center, p2.Point, r1, true); UnitPoint point2 = HitUtil.GetLinePointByDistance(arc2.Center, p2.Point, r2, true); if (HitUtil.Distance(point1, point2) < errorRange) { retPoints.Add(new UnitPointBulge(point2, p2.Bulge, hasMicroConn: p2.HasMicroConn, position: indexCur)); return(retPoints); } var intersects = DrawingOperationHelper.GetIntersectPointBy2Circle(arc1.Center, r1, arc2.Center, r2); var validPoint = new UnitPoint(double.NaN, double.NaN); UnitPoint intersecteArcPoint = new UnitPoint(double.NaN, double.NaN); //筛选有交点,如果有两个点就选距离p2近的点 if (intersects.Count == 1) { validPoint = intersects[0]; } else if (intersects.Count == 2) { validPoint = HitUtil.Distance(intersects[0], p2.Point) < HitUtil.Distance(intersects[1], p2.Point) ? intersects[0] : intersects[1]; } bool closewise = HitUtil.IsClockwiseByCross(p2.Point, point1, point2); if (validPoint.IsEmpty) { if (arc1.Clockwise != closewise || arc2.Clockwise != closewise)//求两个圆弧的切线的交点 { var line1 = DrawingOperationHelper.GetLineEquationByVerticalLine(point1, arc1.Center); var line2 = DrawingOperationHelper.GetLineEquationByVerticalLine(point2, arc2.Center); intersecteArcPoint = DrawingOperationHelper.GetIntersectionPointBy2Line(line1.Item1, line1.Item2, line1.Item3, line2.Item1, line2.Item2, line2.Item3); } } bool completedSmooth = false; //是否完成圆角处理 if (compensationParam.IsSmooth) //圆角处理 { bool needSmooth = false; if (!validPoint.IsEmpty) { double lineAngle = HitUtil.LineAngleR(arc1.Center, validPoint, 0); bool pointInArc = HitUtil.IsPointInArc(HitUtil.RadiansToDegrees(lineAngle), HitUtil.RadiansToDegrees(arc1.StartAngle), HitUtil.RadiansToDegrees(arc1.EndAngle), arc1.Clockwise); needSmooth = !pointInArc; } if (!intersecteArcPoint.IsEmpty || needSmooth) { double bulge = BulgeHelper.GetBulgeFromTwoPointsAndCenter(p2.Point, point1, point2, closewise); retPoints.Add(new UnitPointBulge(point1, bulge, hasMicroConn: p2.HasMicroConn, position: -1 - indexCur)); retPoints.Add(new UnitPointBulge(point2, p2.Bulge, hasMicroConn: p2.HasMicroConn, position: indexCur)); completedSmooth = true; } } if (!completedSmooth) { if (!validPoint.IsEmpty) { retPoints.Add(new UnitPointBulge(validPoint, p2.Bulge, hasMicroConn: p2.HasMicroConn, position: indexCur)); return(retPoints); } else if (!intersecteArcPoint.IsEmpty) { retPoints.Add(new UnitPointBulge(point1, position: indexCur)); retPoints.Add(new UnitPointBulge(intersecteArcPoint, position: indexCur)); retPoints.Add(new UnitPointBulge(point2, p2.Bulge, hasMicroConn: p2.HasMicroConn, position: indexCur)); } else { retPoints.Add(new UnitPointBulge(point1, position: indexCur)); retPoints.Add(new UnitPointBulge(p2.Point, position: indexCur)); retPoints.Add(new UnitPointBulge(point2, p2.Bulge, hasMicroConn: p2.HasMicroConn, position: indexCur)); } } return(retPoints); }
private static List <BridgePoints> GetBridgeByMultiSegLine(MultiSegmentLineBase multiSegLine, UnitPoint p1, UnitPoint p2, BridgingModel param) { List <BridgePoints> retPoints = new List <BridgePoints>(); var line = DrawingOperationHelper.GetLineEquation(p1, p2); double width = param.Width / 2; var oriPoints = multiSegLine.Points; for (int index = 0; index < oriPoints.Count; index++) { int next = (index + 1 == oriPoints.Count) ? 0 : index + 1; UnitPointBulge point1 = oriPoints[index]; UnitPointBulge point2 = oriPoints[next]; if (!multiSegLine.IsCloseFigure && index == oriPoints.Count - 1) { break; } if (!double.IsNaN(point1.Bulge)) { //圆弧 ArcModelMini arcMini = DrawingOperationHelper.GetArcParametersFromBulge(point1.Point, point2.Point, (float)point1.Bulge); arcMini.StartAngle = (float)HitUtil.RadiansToDegrees(arcMini.StartAngle); arcMini.EndAngle = (float)HitUtil.RadiansToDegrees(arcMini.EndAngle); List <UnitPoint> points = DrawingOperationHelper.GetIntersectPointByLineAndCircle(line.Item1, line.Item2, line.Item3, arcMini.Center, arcMini.Radius); var hasPoints = points?.Where(p => !p.IsEmpty && HitUtil.IsPointOnArc(p, 0.000001f, arcMini) && HitUtil.IsPointInLine(p1, p2, p, 0.000001f)).ToList(); if (hasPoints != null && hasPoints.Count > 0) { arcMini.StartAngle = (float)HitUtil.DegreesToRadians(arcMini.StartAngle); arcMini.EndAngle = (float)HitUtil.DegreesToRadians(arcMini.EndAngle); //根据宽度求点 double arcLength = DrawingOperationHelper.GetArcLength(arcMini.Radius, arcMini.SweepAngle); hasPoints?.ForEach(p => { double percent = DrawingOperationHelper.GetPercentInArcByPoint(arcMini, p); //第一个位置点 double length1 = arcLength * (1 - percent) + width; UnitPointBulge retP1 = GetEndPointByLength(oriPoints, index, length1, false); //第二个位置点 double length2 = arcLength * percent + width; UnitPointBulge retP2 = GetEndPointByLength(oriPoints, index, length2, true); var bridge = new BridgePoints(multiSegLine, retP1, retP2, HitUtil.Distance(p1, p)); retPoints.Add(bridge); }); } } else { //直线 var lineABC = DrawingOperationHelper.GetLineEquation(point1.Point, point2.Point); UnitPoint point = DrawingOperationHelper.GetIntersectionPointBy2Line(line.Item1, line.Item2, line.Item3, lineABC.Item1, lineABC.Item2, lineABC.Item3); if (!point.IsEmpty && HitUtil.IsPointInLine(point1.Point, point2.Point, point, 0.000001f) && HitUtil.IsPointInLine(p1, p2, point, 0.000001f)) { //第一个位置点 double lenght1 = HitUtil.Distance(point2.Point, point) + width; UnitPointBulge retP1 = GetEndPointByLength(oriPoints, index, lenght1, false); //第二个位置点 double lenght2 = HitUtil.Distance(point1.Point, point) + width; UnitPointBulge retP2 = GetEndPointByLength(oriPoints, index, lenght2, true); var bridge = new BridgePoints(multiSegLine, retP1, retP2, HitUtil.Distance(p1, point)); retPoints.Add(bridge); } } } return(retPoints); }
private static List <IDrawObject> ConvertToMultiSegLine(ArcBase arc, List <BridgePoints> bridges) { List <IDrawObject> retObjects = new List <IDrawObject>(); if (bridges.Count == 2) { double angle1 = HitUtil.LineAngleR(arc.Center, bridges[0].Point1.Point, 0); double angle2 = HitUtil.LineAngleR(arc.Center, bridges[1].Point1.Point, 0); angle1 = HitUtil.CalAngleSweep(arc.StartAngle, HitUtil.RadiansToDegrees(angle1), arc.IsClockwise); angle2 = HitUtil.CalAngleSweep(arc.StartAngle, HitUtil.RadiansToDegrees(angle2), arc.IsClockwise); if (angle1 > angle2) { bridges.Reverse(); } double bulge1 = BulgeHelper.GetBulgeFromTwoPointsAndCenter(arc.Center, arc.startPoint, bridges[0].Point1.Point, arc.IsClockwise); retObjects.Add(new MultiSegmentLineBase() { IsCloseFigure = false, LayerId = arc.LayerId, GroupParam = CopyUtil.DeepCopy(arc.GroupParam), Points = new List <UnitPointBulge>() { new UnitPointBulge(arc.startPoint, bulge1), bridges[0].Point1 } }); bridges[0].Point2.Bulge = BulgeHelper.GetBulgeFromTwoPointsAndCenter(arc.Center, bridges[0].Point2.Point, bridges[1].Point1.Point, arc.IsClockwise);; retObjects.Add(new MultiSegmentLineBase() { IsCloseFigure = false, LayerId = arc.LayerId, GroupParam = CopyUtil.DeepCopy(arc.GroupParam), Points = new List <UnitPointBulge>() { bridges[0].Point2, bridges[1].Point1 } }); bridges[1].Point2.Bulge = BulgeHelper.GetBulgeFromTwoPointsAndCenter(arc.Center, bridges[1].Point2.Point, arc.endPoint, arc.IsClockwise);; retObjects.Add(new MultiSegmentLineBase() { IsCloseFigure = false, LayerId = arc.LayerId, GroupParam = CopyUtil.DeepCopy(arc.GroupParam), Points = new List <UnitPointBulge>() { bridges[1].Point2, new UnitPointBulge(arc.endPoint, bridges[1].Point2.Bulge) } }); } else if (bridges.Count == 1) { double bulge1 = BulgeHelper.GetBulgeFromTwoPointsAndCenter(arc.Center, arc.startPoint, bridges[0].Point1.Point, arc.IsClockwise); retObjects.Add(new MultiSegmentLineBase() { IsCloseFigure = false, LayerId = arc.LayerId, GroupParam = CopyUtil.DeepCopy(arc.GroupParam), Points = new List <UnitPointBulge>() { new UnitPointBulge(arc.startPoint, bulge1), bridges[0].Point1 } }); bridges[0].Point2.Bulge = BulgeHelper.GetBulgeFromTwoPointsAndCenter(arc.Center, bridges[0].Point2.Point, arc.endPoint, arc.IsClockwise);; retObjects.Add(new MultiSegmentLineBase() { IsCloseFigure = false, LayerId = arc.LayerId, GroupParam = CopyUtil.DeepCopy(arc.GroupParam), Points = new List <UnitPointBulge>() { bridges[0].Point2, new UnitPointBulge(arc.endPoint, bridges[0].Point2.Bulge) } }); } return(retObjects); }