public Arc2D(GeoPoint2D center, double radius, GeoPoint2D StartPoint, GeoPoint2D EndPoint, bool counterclock) : base(center, radius) { start = new Angle(StartPoint, center); sweep = new SweepAngle(StartPoint - center, EndPoint - center); // sweep ist zwischen -pi und +pi, also der Bogen ist maximal ein Halbkreis. // counterclock gibt aber die Richtung vor, deshalb ggf. umdrehen if ((StartPoint | EndPoint) < radius * 1e-10) { if (counterclock) { sweep = SweepAngle.Full; } else { sweep = SweepAngle.FullReverse; } } if (counterclock && sweep <= 0.0) { sweep += 2.0 * Math.PI; } if (!counterclock && sweep >= 0.0) { sweep -= 2.0 * Math.PI; } }
/// <summary> /// Constructor required by deserialization /// </summary> /// <param name="info">SerializationInfo</param> /// <param name="context">StreamingContext</param> protected HatchStyleLines(SerializationInfo info, StreamingContext context) : base(info, context) { lineDistance = (double)info.GetValue("LineDistance", typeof(double)); lineAngle = (Angle)info.GetValue("LineAngle", typeof(Angle)); colorDef = ColorDef.Read("ColorDef", info, context); lineWidth = LineWidth.Read("LineWidth", info, context); linePattern = LinePattern.Read("LinePattern", info, context); try { marginOffset = (double)info.GetValue("MarginOffset", typeof(double)); } catch (SerializationException) { marginOffset = 0.0; } try { number = (int)info.GetValue("NumberOffset", typeof(int)); offset = (double)info.GetValue("Offset", typeof(double)); // warum ist das double? alternate = (bool)info.GetValue("Alternate", typeof(bool)); } catch (SerializationException) { number = 1; offset = SweepAngle.ToLeft; alternate = false; } }
private void RotateWithPlanes() { // get rotation axis from the two planes if (src.Intersect(trg, out GeoPoint loc, out GeoVector dir)) { // set to original position for (int i = 0; i < block.Count; ++i) { block.Child(i).CopyGeometry(originals[i]); } Plane perp = new Plane(loc, dir); // plane perpendicular to rotation axis GeoVector2D from = perp.Project(dir ^ src.Normal); GeoVector2D to = perp.Project(dir ^ trg.Normal); SweepAngle sw = new SweepAngle(from, to); rotationAngle = sw; rotAngleInput.ForceValue(rotationAngle); ModOp m0 = ModOp.Rotate(loc, dir, sw); ModOp m1 = ModOp.Rotate(loc, -dir, sw); GeoVector n0 = m0 * src.Normal; GeoVector n1 = m1 * src.Normal; ModOp m; // not sure, which rotation is better if (Math.Abs(n0 * trg.Normal) > Math.Abs(n1 * trg.Normal)) { m = ModOp.Rotate(loc, dir, sw + GetOffset()); axisVector = dir; } else { m = ModOp.Rotate(loc, -dir, sw + GetOffset()); axisVector = -dir; } block.Modify(m); base.BasePoint = loc; } }
/// <summary> /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Copy (ICurve2D)"/> /// </summary> /// <param name="toCopyFrom"></param> public override void Copy(ICurve2D toCopyFrom) { Arc2D c = toCopyFrom as Arc2D; start = c.start; sweep = c.sweep; base.Copy(toCopyFrom); }
internal void Close() { if (sweep > 0) { sweep = Math.PI * 2.0; } else { sweep = -Math.PI * 2.0; } }
private EntityObject ExportEllipse(GeoObject.Ellipse elli) { netDxf.Entities.EntityObject entity = null; if (elli.IsArc) { Plane dxfPlane; if (elli.CounterClockWise) { dxfPlane = Import.Plane(Vector3(elli.Center), Vector3(elli.Plane.Normal)); } else { dxfPlane = Import.Plane(Vector3(elli.Center), Vector3(-elli.Plane.Normal)); } if (elli.IsCircle) { GeoObject.Ellipse aligned = GeoObject.Ellipse.Construct(); aligned.SetArcPlaneCenterStartEndPoint(dxfPlane, dxfPlane.Project(elli.Center), dxfPlane.Project(elli.StartPoint), dxfPlane.Project(elli.EndPoint), dxfPlane, true); entity = new netDxf.Entities.Arc(Vector3(aligned.Center), aligned.Radius, aligned.StartParameter / Math.PI * 180, (aligned.StartParameter + aligned.SweepParameter) / Math.PI * 180); entity.Normal = Vector3(dxfPlane.Normal); } else { netDxf.Entities.Ellipse expelli = new netDxf.Entities.Ellipse(Vector3(elli.Center), 2 * elli.MajorRadius, 2 * elli.MinorRadius); entity = expelli; entity.Normal = Vector3(elli.Plane.Normal); Plane cdbplane = elli.Plane; GeoVector2D dir = dxfPlane.Project(cdbplane.DirectionX); SweepAngle rot = new SweepAngle(GeoVector2D.XAxis, dir); expelli.Rotation = rot.Degree; SetEllipseParameters(expelli, elli.StartParameter, elli.StartParameter + elli.SweepParameter); } } else { if (elli.IsCircle) { entity = new netDxf.Entities.Circle(Vector3(elli.Center), elli.Radius); entity.Normal = Vector3(elli.Plane.Normal); } else { netDxf.Entities.Ellipse expelli = new netDxf.Entities.Ellipse(Vector3(elli.Center), 2 * elli.MajorRadius, 2 * elli.MinorRadius); entity = expelli; entity.Normal = Vector3(elli.Plane.Normal); Plane dxfplane = Import.Plane(expelli.Center, expelli.Normal); // this plane is not correct, it has to be rotated Plane cdbplane = elli.Plane; GeoVector2D dir = dxfplane.Project(cdbplane.DirectionX); SweepAngle rot = new SweepAngle(GeoVector2D.XAxis, dir); expelli.Rotation = rot.Degree; } } return(entity); }
internal void Close() { // maybe this is wrong, see MakeFullEllipse if (sweep > 0) { sweep = Math.PI * 2.0; } else { sweep = -Math.PI * 2.0; } RecalcQuadrant(); }
/// <summary> /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Trim (double, double)"/> /// </summary> /// <param name="StartPos"></param> /// <param name="EndPos"></param> /// <returns></returns> public override ICurve2D Trim(double StartPos, double EndPos) { Angle st = startPar + StartPos * sweepPar; Angle en = startPar + EndPos * sweepPar; SweepAngle sw = new SweepAngle(st, en, sweepPar > 0.0); if (StartPos == 0.0 && EndPos == 1.0) { sw = sweepPar; } return(new EllipseArc2D(center, majorAxis, minorAxis, st, sw, left, right, bottom, top)); }
internal override void Init(Project pr) { lineDistance = 1.0; lineAngle = Angle.A45; marginOffset = 0.0; number = 1; offset = SweepAngle.ToLeft; alternate = false; lineWidth = pr.LineWidthList.Current; linePattern = pr.LinePatternList.Current; colorDef = pr.ColorList.Current; }
private void OnSetEndPoint(GeoPoint p) { endPoint = p; if (startPointInput.Fixed) { rotAngleInput.Fixed = true; // damit die Aktion nach dem Endpunkt aufhört SweepAngle swAngle = new SweepAngle((GeoVector2D)(base.ActiveDrawingPlane.Project(startPoint) - base.ActiveDrawingPlane.Project(refPoint)), base.ActiveDrawingPlane.Project(endPoint) - base.ActiveDrawingPlane.Project(refPoint)); ModOp m = ModOp.Rotate(base.BasePoint, axisVector, new SweepAngle(swAngle - rotationAngle) + GetOffset()); rotationAngle = swAngle.Radian; block.Modify(m); feedBackEllipse.SetArcPlaneCenterStartEndPoint(ActiveDrawingPlane, ActiveDrawingPlane.Project(BasePoint), ActiveDrawingPlane.Project(startPoint), ActiveDrawingPlane.Project(endPoint), ActiveDrawingPlane, swAngle.Radian > 0.0); } }
private void OnSetStartAngle(Angle a) { double endParameter = ellipse.StartParameter + ellipse.SweepParameter; SweepAngle sa = new SweepAngle(a, new Angle(endParameter), ellipse.SweepParameter > 0.0); using (Frame.Project.Undo.UndoFrame) { ellipse.StartParameter = a.Radian; if (ellipse.IsArc) { ellipse.SweepParameter = sa.Radian; } } }
/// <summary> /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Copy (ICurve2D)"/> /// </summary> /// <param name="toCopyFrom"></param> public override void Copy(ICurve2D toCopyFrom) { EllipseArc2D c = toCopyFrom as EllipseArc2D; start = c.start; sweep = c.sweep; startPar = c.startPar; sweepPar = c.sweepPar; startPoint = c.startPoint; endPoint = c.endPoint; startQuad = c.startQuad; endQuad = c.endQuad; crossingZero = c.crossingZero; base.Copy(toCopyFrom); }
/// <summary> /// Constructor required by deserialization /// </summary> /// <param name="info">SerializationInfo</param> /// <param name="context">StreamingContext</param> protected Arc2D(SerializationInfo info, StreamingContext context) : base(info, context) { start = (Angle)info.GetValue("Start", typeof(Angle)); sweep = (SweepAngle)info.GetValue("Sweep", typeof(SweepAngle)); }
public override int GetHashCode() { unchecked { return((Location.GetHashCode() * 397) ^ (RadiusX.GetHashCode() * 397) ^ (RadiusY.GetHashCode() * 397) ^ (StartAngle.GetHashCode() * 397) ^ SweepAngle.GetHashCode()); } }
/// <summary></summary> /// <returns></returns> public override string ToString() { return(ToString("Center=" + Center.ToString("0.00") + ", StartAngle=" + StartAngle.ToString("0.0") + ", SweepAngle=" + SweepAngle.ToString("0.0"))); }
internal bool Reduce(double precision) { // zuerst die Möglichkeit checken, dass die ganze Kurve in sich zurückgeht: int splitat = -1; double maxBend = 0; for (int i = 2; i < vertex.Length; i++) { SweepAngle sw = new SweepAngle(vertex[i - 1] - vertex[i - 2], vertex[i] - vertex[i - 1]); if (Math.Abs(sw.Radian) > Math.PI - 0.1) { if (Math.Abs(sw.Radian) > maxBend) { maxBend = Math.Abs(sw.Radian); splitat = i - 1; } } } if (splitat >= 0) { GeoPoint2D[] v1 = new GeoPoint2D[splitat + 1]; GeoPoint2D[] v2 = new GeoPoint2D[vertex.Length - splitat]; Array.Copy(vertex, v1, splitat + 1); Array.Copy(vertex, splitat, v2, 0, vertex.Length - splitat); Polyline2D pl1 = Polyline2D.MakePolyline2D(v1); Polyline2D pl2 = Polyline2D.MakePolyline2D(v2); if (pl1 != null && pl2 != null) { ICurve2D fused = pl1.GetFused(pl2, precision); if (fused != null && (fused as Polyline2D).VertexCount < vertex.Length) { this.SetVertices((fused as Polyline2D).Vertex); return(Reduce(precision)); // sollte nicht rekursiv werden, es sei denn, es gibt mehrere Spitzkehren, dann ist es ja gut } } } List <GeoPoint2D> vlist = new List <GeoPoint2D>(); vlist.Add(vertex[0]); int lastInserted = 0; bool reverts = false; for (int i = 2; i < vertex.Length; i++) { bool inserted = true; while (inserted) { inserted = false; for (int j = lastInserted + 1; j < i; j++) { double lp = Geometry.LinePar(vertex[lastInserted], vertex[i], vertex[j]); // Problem: die Polyline geht in sich selbst zurück if (Math.Abs(Geometry.DistPL(vertex[j], vertex[lastInserted], vertex[i])) > precision || lp < 0 || lp > 1) { if (lp < 0 || lp > 1) { reverts = true; } lastInserted = j; vlist.Add(vertex[j]); inserted = true; break; } } } } vlist.Add(vertex[vertex.Length - 1]); if (reverts && vlist.Count >= 3) { // versuche wenigstens am Anfang oder Ende die Situation, dass die Polyline in sich zurückgeht zu bereinigen double lp = Geometry.LinePar(vlist[vlist.Count - 3], vlist[vlist.Count - 2], vlist[vlist.Count - 1]); // der letzte Punkt im vorletzten Segment if (lp >= 0 && lp <= 1 && Math.Abs(Geometry.DistPL(vlist[vlist.Count - 1], vlist[vlist.Count - 2], vlist[vlist.Count - 3])) < precision) { vlist.RemoveAt(vlist.Count - 1); } if (vlist.Count >= 3) { lp = Geometry.LinePar(vlist[2], vlist[1], vlist[0]); // der letzte Punkt im vorletzten Segment if (lp >= 0 && lp <= 1 && Math.Abs(Geometry.DistPL(vlist[0], vlist[1], vlist[2])) < precision) { vlist.RemoveAt(0); } } } if (vlist.Count < vertex.Length) { SetVertices(vlist.ToArray()); return(true); } return(false); }
private bool crossingZero; // geht über die X-Achse private void RecalcQuadrant() { // Berechnung von start und sweep, wird benötigt für die GDI Darstellung Angle MajorAngle = majorAxis.Angle; double s = Math.Sin(MajorAngle); double c = Math.Cos(MajorAngle); ModOp2D toCenter = new ModOp2D(c, s, (-c * center.x - s * center.y), -s, c, (s * center.x - c * center.y)); GeoVector2D startVector = toCenter * startPoint - GeoPoint2D.Origin; GeoVector2D endVector = toCenter * endPoint - GeoPoint2D.Origin; start = startVector.Angle; sweep = new SweepAngle(start, endVector.Angle, sweepPar > 0.0); if (sweep == 0.0) { if (sweepPar > 0.0) { sweep = Math.PI * 2.0; } if (sweepPar < 0.0) { sweep = -Math.PI * 2.0; } } // Berechnung der betroffenen Quadranten startQuad = endQuad = -1; if (startPoint.IsLeftOf(top, right)) { startQuad = 0; } else if (startPoint.IsLeftOf(left, top)) { startQuad = 1; } else if (startPoint.IsLeftOf(bottom, left)) { startQuad = 2; } else if (startPoint.IsLeftOf(right, bottom)) { startQuad = 3; } if (startQuad == -1) { // der Startpunkt muss auf einer Ecke liegen double dmin, d; dmin = Geometry.Dist(startPoint, right); startQuad = 0; d = Geometry.Dist(startPoint, top); if (d < dmin) { startQuad = 1; dmin = d; } d = Geometry.Dist(startPoint, left); if (d < dmin) { startQuad = 2; dmin = d; } if (Geometry.Dist(startPoint, bottom) < dmin) { startQuad = 3; } } if (endPoint.IsLeftOf(top, right)) { endQuad = 0; } else if (endPoint.IsLeftOf(left, top)) { endQuad = 1; } else if (endPoint.IsLeftOf(bottom, left)) { endQuad = 2; } else if (endPoint.IsLeftOf(right, bottom)) { endQuad = 3; } if (endQuad == -1) { double dmin, d; dmin = Geometry.Dist(endPoint, right); endQuad = 0; d = Geometry.Dist(endPoint, top); if (d < dmin) { endQuad = 1; dmin = d; } d = Geometry.Dist(endPoint, left); if (d < dmin) { endQuad = 2; dmin = d; } if (Geometry.Dist(endPoint, bottom) < dmin) { endQuad = 3; } } if ((sweepPar > 0.0) == (GeoVector2D.Orientation(majorAxis, minorAxis) > 0)) { // crossingZero = right.IsLeftOf(endPoint,startPoint); // if (Precision.IsEqual(right,endPoint) && endQuad==0) crossingZero = true; // if (Precision.IsEqual(right,startPoint) && startQuad==3) crossingZero = true; crossingZero = (endQuad < startQuad); if (endQuad == startQuad) { crossingZero = sweepPar > Math.PI; } } else { // crossingZero = right.IsLeftOf(startPoint,endPoint); crossingZero = (startQuad < endQuad); if (endQuad == startQuad) { crossingZero = sweepPar < -Math.PI; } } }
public override void OnMouseMove(MouseEventArgs e, IView vw) { if (e.Button != MouseButtons.Left) { return; } if (modelView == null) { return; } int HOffset = e.X - lastPanPosition.X; int VOffset = e.Y - lastPanPosition.Y; if (VOffset != 0 || HOffset != 0) { Projection Projection = vw.Projection; lastPanPosition = new Point(e.X, e.Y); GeoVector haxis = Projection.InverseProjection * GeoVector.XAxis; GeoVector vaxis = Projection.InverseProjection * GeoVector.YAxis; ModOp mh = ModOp.Rotate(vaxis, SweepAngle.Deg(HOffset / 5.0)); ModOp mv = ModOp.Rotate(haxis, SweepAngle.Deg(VOffset / 5.0)); ModOp project = Projection.UnscaledProjection * mv * mh; // jetzt noch die Z-Achse einrichten. Die kann senkrecht nach oben oder unten // zeigen. Wenn die Z-Achse genau auf den Betrachter zeigt oder genau von ihm weg, // dann wird keine Anpassung vorgenommen, weils sonst zu sehr wackelt GeoVector z = project * GeoVector.ZAxis; if (modelView.ZAxisUp) { const double mindeg = 0.05; // nur etwas aufrichten, aber in jedem Durchlauf if (z.y < -0.1) { // Z-Achse soll nach unten zeigen Angle a = new Angle(-GeoVector2D.YAxis, new GeoVector2D(z.x, z.y)); if (a.Radian > mindeg) { a.Radian = mindeg; } if (a.Radian < -mindeg) { a.Radian = -mindeg; } if (z.x < 0) { project = project * ModOp.Rotate(vaxis ^ haxis, -a.Radian); } else { project = project * ModOp.Rotate(vaxis ^ haxis, a.Radian); } z = project * GeoVector.ZAxis; } else if (z.y > 0.1) { Angle a = new Angle(GeoVector2D.YAxis, new GeoVector2D(z.x, z.y)); if (a.Radian > mindeg) { a.Radian = mindeg; } if (a.Radian < -mindeg) { a.Radian = -mindeg; } if (z.x < 0) { project = project * ModOp.Rotate(vaxis ^ haxis, a.Radian); } else { project = project * ModOp.Rotate(vaxis ^ haxis, -a.Radian); } z = project * GeoVector.ZAxis; } } // Fixpunkt bestimmen Point clcenter = vw.Canvas.ClientRectangle.Location; clcenter.X += vw.Canvas.ClientRectangle.Width / 2; clcenter.Y += vw.Canvas.ClientRectangle.Height / 2; // ium Folgenden ist Temporary auf true zu setzen und ein Mechanismus zu finden // wie der QuadTree von ProjektedModel berechnet werden soll //GeoVector newDirection = mv * mh * Projection.Direction; //GeoVector oldDirection = Projection.Direction; //GeoVector perp = oldDirection ^ newDirection; GeoPoint fixpoint; //if (Settings.GlobalSettings.ContainsSetting("ViewFixPoint")) if (modelView != null && modelView.FixPointValid) { //fixpoint = (GeoPoint)Settings.GlobalSettings.GetValue("ViewFixPoint"); fixpoint = modelView.FixPoint; } else { fixpoint = Projection.UnProject(clcenter); } modelView.SetViewDirection(project, fixpoint, true); if (Math.Abs(HOffset) > Math.Abs(VOffset)) { if (HOffset > 0) { vw.Canvas.Cursor = "PanEast"; } else { vw.Canvas.Cursor = "PanWest"; } } else { if (HOffset > 0) { vw.Canvas.Cursor = "PanSouth"; } else { vw.Canvas.Cursor = "PanNorth"; } } modelView.projectedModelNeedsRecalc = false; } }
/// <summary> /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Reverse ()"/> /// </summary> public override void Reverse() { start = start + sweep; sweep = -sweep; }
/// <summary> /// Constructs a non periodic spherical surface with <paramref name="center"/> and <paramref name="radius"/>. The z-axis will be oriented /// so that the "south pole" falls into an unused part of the sphere. The edges are <paramref name="orientedCurves"/> bound the sphere /// so that when you walk along the curve (<paramref name="outwardOriented"/>==true: on the outside, false: on the inside of the sphere), the /// used surfaces is on the left side of the curve. The curves must all be connected and define one or more closed loops on the surface. /// </summary> /// <param name="center"></param> /// <param name="radius"></param> /// <param name="outwardOriented">true: the center is on the inside, false: the center is on the outside of the surface</param> /// <param name="orientedCurves"></param> public SphericalSurfaceNP(GeoPoint center, double radius, bool outwardOriented, ICurve[] orientedCurves) { // find all intersection points of the curves with a plane through the center // the points must be on a circle (because the curves are on the sphere) and alternating enter and leave the used surface. // we look for the biggest part outside the surface and use its center as the south pole for (int ii = 0; ii < 2; ii++) { // if the first loop doesn't find a solution, run with different points again // exactly 3 arcs, which define an octant of the sphere can make a problem for (int i = 0; i < orientedCurves.Length; i++) { double pos = 0.45; if (ii == 1) { pos = 0.55; } GeoPoint p = orientedCurves[i].PointAt(pos); // not exactly in the middle to avoid special cases GeoVector dir = orientedCurves[i].DirectionAt(pos); GeoVector xdir = p - center; Plane pln; if (outwardOriented) { pln = new Plane(center, xdir, dir ^ xdir); } else { pln = new Plane(center, xdir, xdir ^ dir); } if (ii == 1) { pln.Modify(ModOp.Rotate(center, xdir, SweepAngle.Deg(5))); // slightly rotate to not go exactly through a vertex } double[] pi = orientedCurves[i].GetPlaneIntersection(pln); SortedDictionary <double, bool> positions = new SortedDictionary <double, bool>(); bool ok = false; for (int j = 0; j < pi.Length; j++) { GeoPoint2D pi2d = pln.Project(orientedCurves[i].PointAt(pi[j])); double a = Math.Atan2(pi2d.y, pi2d.x); if (Math.Abs(pi[j] - pos) < 1e-6) { ok = true; a = 0.0; } if (positions.ContainsKey(a)) { ok = false; break; } else { positions[a] = outwardOriented ^ (pln.ToLocal(orientedCurves[i].DirectionAt(pi[j])).z > 0); } } if (ok) { for (int k = 0; k < orientedCurves.Length; k++) { if (k == i) { continue; } pi = orientedCurves[k].GetPlaneIntersection(pln); for (int j = 0; j < pi.Length; j++) { GeoPoint2D pi2d = pln.Project(orientedCurves[k].PointAt(pi[j])); double a = Math.Atan2(pi2d.y, pi2d.x); if (a < 0) { a += Math.PI * 2.0; } if (positions.ContainsKey(a)) { ok = false; break; } else { positions[a] = outwardOriented ^ (pln.ToLocal(orientedCurves[k].DirectionAt(pi[j])).z > 0); } } if (!ok) { break; // two identical intersection points } } } if (ok) { double lastPos = -1; bool lastEnter = false; double sp = 0, d = double.MinValue; foreach (KeyValuePair <double, bool> position in positions) { if (lastPos >= 0) { if (position.Value == lastEnter) { ok = false; // must be alternating break; } if (position.Value && position.Key - lastPos > d) { d = position.Key - lastPos; sp = lastPos; } } lastPos = position.Key; lastEnter = position.Value; } GeoPoint2D soutPole2d = new GeoPoint2D(radius * Math.Cos(sp + d / 2), radius * Math.Sin(sp + d / 2)); if (ok && d > double.MinValue) { this.center = center; zAxis = center - pln.ToGlobal(soutPole2d); zAxis.ArbitraryNormals(out xAxis, out yAxis); if (!outwardOriented) { xAxis = -xAxis; } xAxis.Length = zAxis.Length; yAxis.Length = zAxis.Length; } else { ok = false; } } #if DEBUG // GeoObjectList dbg = DebugGrid; #endif if (ok) { return; } } } }
public string ToString(string format, IFormatProvider formatProvider) { if (this == null) { return(nameof(Ellipse2D)); } var sep = ((formatProvider as CultureInfo) ?? CultureInfo.InvariantCulture).GetNumericListSeparator(); return($"{nameof(EllipticalArc2D)}({nameof(X)}: {X.ToString(format, formatProvider)}{sep} {nameof(Y)}: {Y.ToString(format, formatProvider)}{sep} {nameof(RadiusA)}: {RadiusA.ToString(format, formatProvider)}{sep} {nameof(RadiusB)}: {RadiusB.ToString(format, formatProvider)}{sep} {nameof(Angle)}: {Angle.ToString(format, formatProvider)}{sep} {nameof(StartAngle)}: {StartAngle.ToString(format, formatProvider)}{sep} {nameof(SweepAngle)}: {SweepAngle.ToString(format, formatProvider)})"); }
void IPaintTo3D.Arc(GeoPoint center, GeoVector majorAxis, GeoVector minorAxis, double startParameter, double sweepParameter) { try { GeoVector normal = majorAxis ^ minorAxis; // normale der Ebene des Bogens // wird der Bogen von vorne oder hinten betrachtet? // statt projection.Direction besser die Richtung zum Mittelpunkt (bei perspektivischer Projektion) double sc = projection.Direction.Normalized * normal.Normalized; if (Math.Abs(sc) < 1e-6) { // eine Linie GeoVector dir = normal ^ projection.Direction; // Richtung der Linie double pmin, pmax; double par = Geometry.LinePar(center, dir, center + Math.Cos(startParameter) * majorAxis + Math.Sin(startParameter) * minorAxis); pmin = pmax = par; par = Geometry.LinePar(center, dir, center + Math.Cos(startParameter + sweepParameter) * majorAxis + Math.Sin(startParameter + sweepParameter) * minorAxis); if (par < pmin) { pmin = par; } if (par > pmax) { pmax = par; } // fehlt noch: jetzt noch die Achsenpunkt abprüfen... (this as IPaintTo3D).Polyline(new GeoPoint[] { center + pmin * dir, center + pmax * dir }); } else { GeoPoint2D center2d = projection.Project(center); GeoVector2D maj2D = projection.Project(center + majorAxis) - center2d; GeoVector2D min2D = projection.Project(center + minorAxis) - center2d; if (maj2D.IsNullVector() || min2D.IsNullVector()) { // eigentlich auch eine Linie return; } GeoPoint2D sp = center2d + Math.Cos(startParameter) * maj2D + Math.Sin(startParameter) * min2D; GeoPoint2D ep = center2d + Math.Cos(startParameter + sweepParameter) * maj2D + Math.Sin(startParameter + sweepParameter) * min2D; bool counterclock = sweepParameter > 0.0; //if (normal.z > 0.0) counterclock = !counterclock; EllipseArc2D ea2d = EllipseArc2D.Create(center2d, maj2D, min2D, sp, ep, counterclock); ea2d.MakePositivOriented(); GeoVector2D prmaj2D, prmin2D; // Geometry.PrincipalAxis(maj2D, min2D, out prmaj2D, out prmin2D); prmaj2D = ea2d.MajorAxis; prmin2D = ea2d.MinorAxis; Angle rot = prmaj2D.Angle; //ModOp2D toHorizontal = ModOp2D.Rotate(center2d, -rot.Radian); ModOp2D fromHorizontal = ModOp2D.Rotate(center2d, rot.Radian); SweepAngle swapar = new SweepAngle(ea2d.StartPoint - center2d, ea2d.EndPoint - center2d); if (counterclock && swapar < 0) { swapar += 360; } if (!counterclock && swapar > 0) { swapar -= 360; } float swPar = (float)(ea2d.axisSweep / Math.PI * 180); float stPar = (float)(ea2d.axisStart / Math.PI * 180); if (sweepParameter >= Math.PI * 2.0 || sweepParameter <= -Math.PI * 2.0) { // Notlösung wg. ERSACAD und wg. Nürnberger 5.12.13 swPar = 360.0f; } try { Matrix r = fromHorizontal.Matrix2D; double maxRad = prmaj2D.Length; double minRad = prmin2D.Length; if ((maxRad + minRad) * Projection.WorldToDeviceFactor < 1) { // sonst gibt es ein out of memory exception if (graphicsPath != null) { // kann auch schräge Ellipsen zufügen mit Transformation GraphicsPath tmpPath = new GraphicsPath(); tmpPath.AddLine((float)center2d.x, (float)center2d.y, (float)center2d.x, (float)center2d.y); tmpPath.Transform(r); graphicsPath.AddPath(tmpPath, true); } else { Pen drawPen = MakePen(); using (drawPen) { using (new Transform(graphics, r, false)) { // wenigstens einen Pixel darstellen graphics.DrawLine(drawPen, (float)(center2d.x - 0.5), (float)center2d.y, (float)(center2d.x + 0.5), (float)center2d.y); } } } } else { if (graphicsPath != null) { // kann auch schräge Ellipsen zufügen mit Transformation GraphicsPath tmpPath = new GraphicsPath(); tmpPath.AddArc((float)(center2d.x - maxRad), (float)(center2d.y - minRad), (float)(2.0 * maxRad), (float)(2.0 * minRad), stPar, swPar); tmpPath.Transform(r); graphicsPath.AddPath(tmpPath, true); } else { Pen drawPen = MakePen(); using (drawPen) { using (new Transform(graphics, r, false)) { graphics.DrawArc(drawPen, (float)(center2d.x - maxRad), (float)(center2d.y - minRad), (float)(2.0 * maxRad), (float)(2.0 * minRad), stPar, swPar); } } } } } catch (ArgumentException) { } catch (ModOpException) { } catch (OutOfMemoryException) { } } } catch { // damit es sicher durchläuft. z.B. eine Ellipse, bei der beide Achsen dieselbe Richtung haben, erzeugt eine ModOp Exception } }
private void OnSetEndAngle(Angle a) { SweepAngle sa = new SweepAngle(new Angle(ellipse.StartParameter), a, ellipse.SweepParameter > 0.0); ellipse.SweepParameter = sa.Radian; }
/// <summary> /// Constructs a circular arc in 2D. /// </summary> /// <param name="center">Center of the arc</param> /// <param name="radius">Radius of the Arc</param> /// <param name="start">Startangle of the arc (x-axis is 0)</param> /// <param name="sweep">Sweepangle of the arc -2*pi<=s<=2*pi</param> public Arc2D(GeoPoint2D center, double radius, Angle start, SweepAngle sweep) : base(center, radius) { this.start = start; this.sweep = sweep; }
private void OnSetEndAngle(Angle a) { SweepAngle sa = new SweepAngle(new Angle(circle.StartParameter), a, circle.SweepParameter > 0.0); circle.SweepParameter = sa.Radian; }