/// <summary> /// Overrides <see cref="CADability.GeoObject.ISurfaceImpl.SameGeometry (BoundingRect, ISurface, BoundingRect, double, out ModOp2D)"/> /// </summary> /// <param name="thisBounds"></param> /// <param name="other"></param> /// <param name="otherBounds"></param> /// <param name="precision"></param> /// <param name="firstToSecond"></param> /// <returns></returns> public override bool SameGeometry(BoundingRect thisBounds, ISurface other, BoundingRect otherBounds, double precision, out ModOp2D firstToSecond) { firstToSecond = ModOp2D.Null; if (other is PlaneSurface) { PlaneSurface second = other as PlaneSurface; GeoPoint p = PointAt(thisBounds.GetCenter()); if (Math.Abs(second.Plane.Distance(p)) > precision) { return(false); } p = second.PointAt(otherBounds.GetCenter()); if (Math.Abs(Plane.Distance(p)) > precision) { return(false); } if (Precision.SameDirection(Normal, second.Normal, false)) { GeoPoint2D[] src = new GeoPoint2D[] { GeoPoint2D.Origin, new GeoPoint2D(1, 0), new GeoPoint2D(0, 1) }; GeoPoint2D[] dst = new GeoPoint2D[3]; for (int i = 0; i < 3; ++i) { dst[i] = second.PositionOf(PointAt(src[i])); } firstToSecond = ModOp2D.Fit(src, dst, true); return(true); } else { return(false); } } return(base.SameGeometry(thisBounds, other, otherBounds, precision, out firstToSecond)); }
/// <summary> /// Overrides <see cref="CADability.GeoObject.ISurfaceImpl.SameGeometry (BoundingRect, ISurface, BoundingRect, double, out ModOp2D)"/> /// </summary> /// <param name="thisBounds"></param> /// <param name="other"></param> /// <param name="otherBounds"></param> /// <param name="precision"></param> /// <param name="firstToSecond"></param> /// <returns></returns> public override bool SameGeometry(BoundingRect thisBounds, ISurface other, BoundingRect otherBounds, double precision, out ModOp2D firstToSecond) { if (other is SurfaceOfLinearExtrusion) { firstToSecond = ModOp2D.Null; SurfaceOfLinearExtrusion sleother = other as SurfaceOfLinearExtrusion; // es würde genügen, wenn die beiden Kurven sich überlappen. Dann auf das Überlappungsintervall testen bool reverse; if (!Curves.SameGeometry(BasisCurve, sleother.BasisCurve, precision, out reverse)) { return(false); } // zwei Extrempunkte bestimmen, damit sollte es OK sein GeoPoint2D uv1 = new GeoPoint2D(curveStartParameter, 0.0); GeoPoint p1 = PointAt(uv1); GeoPoint2D uv2 = sleother.PositionOf(p1); GeoPoint p2 = sleother.PointAt(uv2); if ((p1 | p2) > precision) { return(false); } uv1 = new GeoPoint2D(curveEndParameter, 1.0); p1 = PointAt(uv1); uv2 = sleother.PositionOf(p1); p2 = sleother.PointAt(uv2); if ((p1 | p2) > precision) { return(false); } firstToSecond = ModOp2D.Translate(uv2 - uv1); return(true); } return(base.SameGeometry(thisBounds, other, otherBounds, precision, out firstToSecond)); }
void IView.ZoomToRect(BoundingRect World2D) { Rectangle screen = (this as IView).DisplayRectangle; double factor; // Höhe und Breite==0 soll einen Fehler liefern! if (World2D.Height == 0.0) { factor = screen.Width / World2D.Width; } else if (World2D.Width == 0.0) { factor = screen.Height / World2D.Height; } else { factor = Math.Min(screen.Width / World2D.Width, screen.Height / World2D.Height); } // wie ist das mit der Y-Richtung in screen? double dx = (screen.Right + screen.Left) / 2.0 - (World2D.Right + World2D.Left) / 2.0 * factor; double dy = (screen.Top + screen.Bottom) / 2.0 + (World2D.Top + World2D.Bottom) / 2.0 * factor; layoutToScreen = new ModOp2D(factor, 0.0, dx, 0.0, -factor, dy); screenToLayout = layoutToScreen.GetInverse(); // ginge auch einfacher }
// eigentlich eine Untergruppe für alle Patches public LayoutView(Layout layout, Project project) { this.project = project; this.layout = layout; screenToLayout = layoutToScreen = ModOp2D.Null; base.resourceId = "LayoutView"; // printDocument = project.printDocument; printDocument = new PrintDocument(); if (printDocument != null) { if (layout.pageSettings != null) { printDocument.DefaultPageSettings = layout.pageSettings; } else { if (project.printDocument != null) { printDocument.DefaultPageSettings = (PageSettings)project.printDocument.DefaultPageSettings.Clone(); } else { printDocument.DefaultPageSettings.Landscape = layout.PaperWidth > layout.PaperHeight; } } } }
public static EllipseArc2D Create(GeoPoint2D center, GeoVector2D majorAxis, GeoVector2D minorAxis, GeoPoint2D startPoint, GeoPoint2D endPoint, bool counterClock) { // bestimme die beiden Winkel GeoVector2D majAx; GeoVector2D minAx; GeoPoint2D left, right, bottom, top; Geometry.PrincipalAxis(center, majorAxis, minorAxis, out majAx, out minAx, out left, out right, out bottom, out top, false); ModOp2D toUnit = ModOp2D.Fit(new GeoPoint2D[] { center, center + majAx, center + minAx }, new GeoPoint2D[] { GeoPoint2D.Origin, GeoPoint2D.Origin + GeoVector2D.XAxis, GeoPoint2D.Origin + GeoVector2D.YAxis }, true); GeoPoint2D p = toUnit * startPoint; double sa = p.ToVector().Angle.Radian; p = toUnit * endPoint; double ea = p.ToVector().Angle.Radian; double sw; if (counterClock) { sw = ea - sa; if (sw <= 0.0) { sw += Math.PI * 2.0; // geändert auf <= bzw. >=, da sonst aus Vollkreisen Leerkreise werden } } else { sw = ea - sa; if (sw >= 0.0) { sw -= Math.PI * 2.0; } } return(new EllipseArc2D(center, majAx, minAx, sa, sw, left, right, bottom, top)); }
public override ICurve2D GetModified(ModOp2D m) { Polyline2D res = this.Clone() as Polyline2D; res.Modify(m); return(res); }
public void Modify(ModOp2D m) // gehört das nicht in das ICurve Interface? { for (int i = 0; i < vertex.Length; ++i) { vertex[i] = m * vertex[i]; } }
private Plane zPosition; // die Raum-Ebene, in deren Mittelpunkt der Kreis bezüglich seine 2d Darstellung liegt internal void RecalcUnitCircle() { // berechnen der beiden ModOps fromUnitCircle und toUnitCircle // Achtung: das berücksichtigt nicht ein Linkssystem. Das ist somit eigentlich falsch // im Linkssystem müsste das Vorzeichen von MinorRadius negativ sein, damit die Matrix stimmt! double MajorRadius = majorAxis.Length; double MinorRadius = minorAxis.Length; if (GeoVector2D.Orientation(majorAxis, minorAxis) < 0) { // eingeführt wg. dem Umdrehen eines Faces mit elliptischen Begrenzungen (11.3.15), Datei 97871_086103_032.cdb, nach Shell.AssertOutwardOrientation stimmt das Face Nr. 8 nicht mehr MinorRadius = -MinorRadius; } if (MajorRadius == 0.0 || MinorRadius == 0.0) { fromUnitCircle = toUnitCircle = ModOp2D.Identity; } else { Angle MajorAngle = majorAxis.Angle; double s = Math.Sin(MajorAngle); double c = Math.Cos(MajorAngle); toUnitCircle = new ModOp2D(c / MajorRadius, s / MajorRadius, (-c * center.x - s * center.y) / MajorRadius, -s / MinorRadius, c / MinorRadius, (s * center.x - c * center.y) / MinorRadius); fromUnitCircle = new ModOp2D(MajorRadius * c, -MinorRadius * s, center.x, MajorRadius * s, MinorRadius * c, center.y); } }
internal BoundingRect GetModified(ModOp2D m) { BoundingRect res = new BoundingRect(this); res.Modify(m); return(res); }
public ScaledSurface(ISurface original, double fu, double fv) { this.fu = fu; this.fv = fv; this.original = original; scale = ModOp2D.Scale(fu, fv); unscale = scale.GetInverse(); }
/// <summary> /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.GetModified (ModOp2D)"/> /// </summary> /// <param name="m"></param> /// <returns></returns> public override ICurve2D GetModified(ModOp2D m) { // allgemeine Lösung, wird für Kreis und Ellipse übernommen Line2D res = Clone() as Line2D; res.startPoint = m * startPoint; res.endPoint = m * endPoint; return(res); }
ICurve2D ICurve2D.GetModified(ModOp2D m) { return(theCurve.GetModified(m)); // war vorher so: nicht sicher ob das jemand so braucht, macht Probleme wenn nicht geklippt //Curve2DAspect c2da = Clone(); //c2da.MakeClipped(); //c2da.clippedCurve = c2da.clippedCurve.GetModified(m); //// wie Move. Lösung: ModOp2D ansammeln //return c2da; }
/// <summary> /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.GetModified (ModOp2D)"/> /// </summary> /// <param name="m"></param> /// <returns></returns> public override ICurve2D GetModified(ModOp2D m) { // es ist wichtig hier zu überschreiben, die Basisfunktionalität macht aus einem 360° // Kreisbogen einen Kreis und der Anfangspunkt geht verloren. Diese Information ist aber // für die Edges wichtig. if (m.IsIsogonal) { bool cc = sweep > 0.0; if (m.Determinant < 0.0) { cc = !cc; } Arc2D res = new Arc2D(m * Center, m.Factor * Radius, m * StartPoint, m * EndPoint, cc); if (m.Determinant < 0.0) { res.sweep = -sweep; // das schaltet die Fälle aus, wo Unsicherheit zwischen 0 und 360° besteht } else { res.sweep = sweep; } return(res); } else { //double sw = sweep; //if (m.Determinant < 0.0) sw = -sw; GeoVector2D majorAxis; GeoVector2D minorAxis; GeoPoint2D left, right, bottom, top; bool cc = sweep > 0.0; if (m.Determinant < 0.0) { cc = !cc; } majorAxis = m * (Radius * GeoVector2D.XAxis); minorAxis = m * (Radius * GeoVector2D.YAxis); if (Math.Abs(majorAxis.Length - minorAxis.Length) < (majorAxis.Length + minorAxis.Length) * 1e-6) { return(new Arc2D(m * Center, Math.Abs(m.Determinant * Radius), m * StartPoint, m * EndPoint, cc)); } Geometry.PrincipalAxis(m * Center, m * (Radius * GeoVector2D.XAxis), m * (Radius * GeoVector2D.YAxis), out majorAxis, out minorAxis, out left, out right, out bottom, out top, false); // geändert wg. Fehler in IsIsogonal Fall, noch nicht getestet return(EllipseArc2D.Create(m * Center, majorAxis, minorAxis, m * StartPoint, m * EndPoint, cc)); //if (m.Determinant < 0.0) //{ // return new EllipseArc2D(m * Center, m * (Radius * GeoVector2D.XAxis), m * (Radius * GeoVector2D.YAxis), start + sweep, sw, left, right, bottom, top); //} //else //{ // return new EllipseArc2D(m * Center, m * (Radius * GeoVector2D.XAxis), m * (Radius * GeoVector2D.YAxis), start, sw, left, right, bottom, top); //} } }
public override double PositionOf(GeoPoint2D p) { ModOp2D toUnit = fromUnit.GetInverse(); double u = (toUnit * p).x; #if DEBUG GeoPoint2D tp = PointAt(ParToPos(u)); double d = p | tp; #endif return(ParToPos(u)); }
public override void Copy(ICurve2D toCopyFrom) { SineCurve2D other = toCopyFrom as SineCurve2D; if (other is SineCurve2D) { ustart = other.ustart; udiff = other.udiff; fromUnit = other.fromUnit; } }
public PlanePolygon(GeoPoint2D uv, GeoPoint loc, GeoVector diru, GeoVector dirv, GeoPoint edgeStart, GeoPoint edgeEnd, Tangulation tangulation) { // TODO: Complete member initialization plane = new Plane(loc, diru, dirv); toUV = ModOp2D.Translate(uv.x, uv.y) * ModOp2D.Fit(new GeoVector2D[] { GeoVector2D.XAxis, GeoVector2D.YAxis }, new GeoVector2D[] { plane.Project(diru), plane.Project(dirv) }); polygon = new List <GeoPoint2D>(); polygon.Add(plane.Project(edgeStart)); // die beiden Punkte geben die Linie an, die die Ebene begrenzt polygon.Add(plane.Project(edgeEnd)); isOpen = true; // die Linie "halbiert" die Ebene, links davon ist innerhalb extend = BoundingCube.EmptyBoundingCube; }
/// <summary> /// Modifies the rectangle by the provided <see cref="ModOp2D"/>. The resulting rectangle contains the modified /// vertices of this rectangle /// </summary> /// <param name="m">Modification to use</param> public void Modify(ModOp2D m) { GeoPoint2D p1 = m * new GeoPoint2D(Left, Bottom); GeoPoint2D p2 = m * new GeoPoint2D(Left, Top); GeoPoint2D p3 = m * new GeoPoint2D(Right, Bottom); GeoPoint2D p4 = m * new GeoPoint2D(Right, Top); Left = Right = p1.x; Bottom = Top = p1.y; MinMax(p2); MinMax(p3); MinMax(p4); }
public override void CopyData(ISurface CopyFrom) { NonPeriodicSurface nps = CopyFrom as NonPeriodicSurface; if (nps != null) { periodicSurface = nps.periodicSurface; periodicBounds = nps.periodicBounds; hasPole = nps.hasPole; fullPeriod = nps.fullPeriod; toNonPeriodicBounds = nps.toNonPeriodicBounds; toPeriodicBounds = nps.toPeriodicBounds; } }
/// <summary> /// This method is used by a <see cref="Hatch"/> object to calculate its contents. It generates a /// set of parallel lines according to <see cref="LineDistance"/> and <see cref="LineAngle"/> /// and clips them with the given shape. The lines are projected into the 3D world /// by the given plane. <seealso cref="CompoundShape.Clip"/> /// </summary> /// <param name="shape">shape of the hatch object</param> /// <param name="plane">local plane of the hatch object</param> /// <returns></returns> public override GeoObjectList GenerateContent(CompoundShape shape, Plane plane) { GeoObjectList res = new GeoObjectList(); if (shape == null) { return(res); } if (marginOffset != 0.0) { shape.Approximate(false, Settings.GlobalSettings.GetDoubleValue("Approximate.Precision", 0.01)); shape = shape.Shrink(marginOffset); } for (int i = 0; i < Math.Max(1, number); ++i) { double a = lineAngle.Radian + i * (double)offset; ModOp2D m = ModOp2D.Rotate(new SweepAngle(-a)); BoundingRect ext = shape.GetExtent(); ext.Modify(m); // ext ist jetzt waagrecht, u.U. zu groß, was aber egal ist m = ModOp2D.Rotate(new SweepAngle(a)); // die umgekehrte ModOp int alt = 0; // eine Linie soll durch die Mitte gehen double c = (ext.Bottom + ext.Top) / 2.0; double num = Math.Ceiling((c - ext.Bottom) / lineDistance); ext.Bottom = c - num * lineDistance; // das untere Ende sowei nach unten verschoben, dass eine Linie durch die mitte geht // das ist wichtig, weil sonst manche Schraffuren nicht zu picken sind, da keine Linie darin erscheint // da eine Schraffur meist nur aus einem SimpleShape besteht, gibt es immer eine Linie durch die Mitte for (double y = ext.Bottom; y < ext.Top; y += lineDistance) { GeoPoint2D startPoint = m * new GeoPoint2D(ext.Left, y); GeoPoint2D endPoint = m * new GeoPoint2D(ext.Right, y); Line2D l = new Line2D(startPoint, endPoint); if (alternate && ((alt & 0x01) != 0)) { l.Reverse(); } double[] seg = shape.Clip(l, true); for (int j = 0; j < seg.Length; j += 2) { IGeoObject go = l.Trim(seg[j], seg[j + 1]).MakeGeoObject(plane); (go as ILineWidth).LineWidth = lineWidth; (go as ILinePattern).LinePattern = linePattern; (go as IColorDef).ColorDef = colorDef; res.Add(go); } ++alt; } } return(res); }
internal void GetAxisAlignedEllipse(out double MajorRadius, out double MinorRadius, out ModOp2D toAxis, out ModOp2D fromAxis) { MajorRadius = majorAxis.Length; MinorRadius = minorAxis.Length; if (MajorRadius == 0.0 || MinorRadius == 0.0) { fromAxis = toAxis = ModOp2D.Identity; } else { // noch überprüfen dass MajorAxis>MinorAxis ist Angle MajorAngle = majorAxis.Angle; double s = Math.Sin(MajorAngle); double c = Math.Cos(MajorAngle); toAxis = new ModOp2D(c, s, (-c * center.x - s * center.y), -s, c, (s * center.x - c * center.y)); fromAxis = new ModOp2D(c, -s, center.x, s, c, center.y); } }
public InfiniteLine2D(GeoPoint2D startPoint, GeoPoint2D endPoint) { this.startPoint = startPoint; direction = endPoint - startPoint; Angle a = direction.Angle; if (Precision.IsEqual(a, Angle.A0) || Precision.IsEqual(a, Angle.A180)) { toXAxis = ModOp2D.Translate(0.0, -startPoint.y); } else { double l = -startPoint.y / direction.y; // != 0.0, da nicht horizontal double x = startPoint.x + l * direction.x; // double y = startPoint.y+l*direction.y; toXAxis = ModOp2D.Rotate(new GeoPoint2D(x, 0.0), new SweepAngle(-a)); } }
/// <summary> /// Overrides <see cref="CADability.GeoObject.ISurfaceImpl.SameGeometry (BoundingRect, ISurface, BoundingRect, double, out ModOp2D)"/> /// </summary> /// <param name="thisBounds"></param> /// <param name="other"></param> /// <param name="otherBounds"></param> /// <param name="precision"></param> /// <param name="firstToSecond"></param> /// <returns></returns> public override bool SameGeometry(BoundingRect thisBounds, ISurface other, BoundingRect otherBounds, double precision, out ModOp2D firstToSecond) { if (other is HelicalSurface) { firstToSecond = ModOp2D.Null; HelicalSurface srother = other as HelicalSurface; bool reverse; if (!Curves.SameGeometry(BasisCurve, srother.BasisCurve, precision, out reverse)) { return(false); } if ((Location | srother.Location) > precision) { return(false); } if (Math.Abs(pitch - srother.pitch) > precision) { return(false); } GeoPoint2D uv1 = new GeoPoint2D(curveStartParameter, 0.0); GeoPoint p1 = PointAt(uv1); GeoPoint2D uv2 = srother.PositionOf(p1); GeoPoint p2 = srother.PointAt(uv2); if ((p1 | p2) > precision) { return(false); } uv1 = new GeoPoint2D(curveEndParameter, 0.0); p1 = PointAt(uv1); uv2 = srother.PositionOf(p1); p2 = srother.PointAt(uv2); if ((p1 | p2) > precision) { return(false); } firstToSecond = ModOp2D.Translate(uv2 - uv1); return(true); } return(base.SameGeometry(thisBounds, other, otherBounds, precision, out firstToSecond)); }
/// <summary> /// Clips the bitmap according to the provided shape and plane. The BitmapBits are replaced by /// transparent pixels, the original bits are lost. Setting another clip area doesn't restore already clipped /// pixels. (Ofcourse undo restores the original bitmap bits) /// </summary> /// <param name="plane">The plane as a reference system for the shape</param> /// <param name="shape">The shape for the clip operation</param> public void Clip(Plane plane, CompoundShape shape) { #if !WEBASSEMBLY Plane pln = new Plane(location, directionWidth, directionHeight); CompoundShape prsh = shape.Project(plane, pln); ModOp2D m = ModOp2D.Scale(bitmap.Width / directionWidth.Length, -bitmap.Height / directionHeight.Length); prsh = prsh.GetModified(m); m = ModOp2D.Translate(0, bitmap.Height); prsh = prsh.GetModified(m); GraphicsPath gp = prsh.CreateGraphicsPath(); using (new Changing(this)) { Region rg = new Region(gp); Bitmap clone = bitmap.Clone() as Bitmap; Graphics graphics = Graphics.FromImage(bitmap); graphics.Clear(Color.FromArgb(0, 0, 0, 0)); graphics.SetClip(rg, CombineMode.Replace); graphics.DrawImage(clone, new System.Drawing.Point(0, 0)); graphics.Dispose(); } #endif }
public override bool SameGeometry(BoundingRect thisBounds, ISurface other, BoundingRect otherBounds, double precision, out ModOp2D firstToSecond) { if (other is RuledSurface) { RuledSurface rsother = other as RuledSurface; if ((firstCurve.SameGeometry(rsother.firstCurve, precision) && secondCurve.SameGeometry(rsother.secondCurve, precision)) || (firstCurve.SameGeometry(rsother.secondCurve, precision) && secondCurve.SameGeometry(rsother.firstCurve, precision))) { GeoPoint2D[] srcPoints = new GeoPoint2D[] { GeoPoint2D.Origin, new GeoPoint2D(1, 0), new GeoPoint2D(0, 1) }; GeoPoint2D[] dstPoints = new GeoPoint2D[3]; for (int i = 0; i < dstPoints.Length; i++) { dstPoints[i] = rsother.PositionOf(this.PointAt(srcPoints[i])); } firstToSecond = ModOp2D.Fit(srcPoints, dstPoints, true); return(true); } firstToSecond = ModOp2D.Null; return(false); } return(base.SameGeometry(thisBounds, other, otherBounds, precision, out firstToSecond)); }
public override ModOp2D ReverseOrientation() { GeoPoint2D[] from = new GeoPoint2D[3]; from[0] = new GeoPoint2D(0.5, 0.5); from[1] = new GeoPoint2D(0.5, 0.7); from[2] = new GeoPoint2D(0.7, 0.5); GeoPoint[] from3d = new GeoPoint[3]; for (int i = 0; i < 3; i++) { from3d[i] = PointAt(from[i]); } periodicSurface.ReverseOrientation(); Init(periodicSurface.IsUPeriodic); //toNonPeriodicBounds = toNonPeriodicBounds * ModOp2D.Scale(-1, 1); //toPeriodicBounds = toNonPeriodicBounds.GetInverse(); GeoPoint2D[] to = new GeoPoint2D[3]; for (int i = 0; i < 3; i++) { to[i] = PositionOf(from3d[i]); } return(ModOp2D.Fit(from, to, true)); }
/// <summary> /// Overrides IGeoObjectImpl.<see cref="IGeoObjectImpl.Modify"/> and implements IGeoObject.<see cref="IGeoObject.Modify"/>. /// </summary> /// <param name="m">see <see cref="IGeoObject.Modify"/></param> public override void Modify(ModOp m) { using (new Changing(this, "ModifyInverse", m)) { // die ModOp wird in zwei Komponente aufgeteilt: // eine Skalierungsfreie, die auf die Ebene angewendet wird // und eine Skalierung, die nochmal auf die compoundShape wirkt try { Plane newPlane = new Plane(m * plane.Location, m * plane.DirectionX, m * plane.DirectionY); // die Ebene verändert sich gemäß der Matrix m, wie verändert sich die Umrandung im 2D? // Die brutale Methode: aus den bekannten Veränderungen von 3 Punkten die Matrix bestimmen // das funktioniert, alles andere hat bislang nicht geklappt GeoPoint2D[] src = new GeoPoint2D[3]; GeoPoint2D[] dst = new GeoPoint2D[3]; src[0] = GeoPoint2D.Origin; src[1] = GeoPoint2D.Origin + GeoVector2D.XAxis; src[2] = GeoPoint2D.Origin + GeoVector2D.YAxis; dst[0] = newPlane.Project(m * plane.ToGlobal(src[0])); dst[1] = newPlane.Project(m * plane.ToGlobal(src[1])); dst[2] = newPlane.Project(m * plane.ToGlobal(src[2])); ModOp2D m2d = ModOp2D.Fit(src, dst, true); compoundShape = compoundShape.GetModified(m2d); plane = newPlane; if (m.Mode == ModOp.ModificationMode.Translation && base.Count > 0) { containedObjects.Modify(m); } else { needsRecalc = true; } } catch (PlaneException) { } // neue Ebene enthält Nullvector } }
/// <summary> /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.GetModified (ModOp2D)"/> /// </summary> /// <param name="m"></param> /// <returns></returns> public override ICurve2D GetModified(ModOp2D m) { #if DEBUG ////DebuggerContainer dc = new DebuggerContainer(); ////GeoPoint[] tst = new GeoPoint[10]; ////for (int i = 0; i < 10; i++) ////{ //// tst[i] = new GeoPoint(PointAt(i / 9.0)); ////} ////Polyline pl = Polyline.Construct(); ////try ////{ //// pl.SetPoints(tst, false); //// dc.Add(pl, 0); ////} ////catch { } ////EllipseArc2D dbg = EllipseArc2D.Create(m * center, m * majorAxis, m * minorAxis, m * StartPoint, m * EndPoint, counterClock); ////for (int i = 0; i < 10; i++) ////{ //// tst[i] = new GeoPoint(dbg.PointAt(i / 9.0)); ////} ////pl = Polyline.Construct(); ////try ////{ //// pl.SetPoints(tst, false); //// dc.Add(pl, 1); ////} ////catch { } #endif EllipseArc2D res = EllipseArc2D.Create(m * center, m * majorAxis, m * minorAxis, m * StartPoint, m * EndPoint, counterClock); if (Math.Abs(res.sweepPar) < 1e-6 && Math.Abs(this.sweepPar) > Math.PI * 2.0 - 1e-6) { res.sweepPar = this.sweepPar; } return(res); }
public override bool SameGeometry(BoundingRect thisBounds, ISurface other, BoundingRect otherBounds, double precision, out ModOp2D firstToSecond) { if (other is NonPeriodicSurface nps) { if (nps.periodicSurface.SameGeometry(nps.periodicBounds, periodicSurface, periodicBounds, precision, out ModOp2D periodicFirstToSecond)) { firstToSecond = ModOp2D.Null; return(true); } firstToSecond = ModOp2D.Null; return(false); } return(base.SameGeometry(thisBounds, other, otherBounds, precision, out firstToSecond)); }
private void Init(bool uPeriodic) { hasPole = false; fullPeriod = false; if (uPeriodic) { fullPeriod = true; double[] sv = periodicSurface.GetVSingularities(); if (sv != null && sv.Length > 1) { List <double> lsv = new List <double>(sv); for (int i = lsv.Count - 1; i >= 0; --i) { if (lsv[i] < periodicBounds.Bottom || lsv[i] > periodicBounds.Top) { lsv.RemoveAt(i); } } sv = lsv.ToArray(); } if (sv != null && sv.Length > 0) { if (sv.Length == 1) { hasPole = true; if (sv[0] == periodicBounds.Bottom) { // bounds.Bottom => 0.0, bounds.Top => 1.0 // bounds.Left => 0, bountd.Right => 2*pi double fvu = 2.0 * Math.PI / periodicBounds.Width; double fuv = 1.0 / periodicBounds.Height; toNonPeriodicBounds = new ModOp2D(fvu, 0, -fvu * periodicBounds.Left, 0, fuv, -fuv * periodicBounds.Bottom); } else if (sv[0] == periodicBounds.Top) { // bounds.Bottom => 0.0, bounds.Top => 1.0 // bounds.Left => 2*pi, bountd.Right => 0 double fvu = 2.0 * Math.PI / periodicBounds.Width; double fuv = 1.0 / periodicBounds.Height; toNonPeriodicBounds = new ModOp2D(-fvu, 0, fvu * periodicBounds.Right, 0, fuv, -fuv * periodicBounds.Bottom); } else { throw new ApplicationException("pole must be on border"); } } else { throw new ApplicationException("more than one pole"); } } else { // bounds.Bottom => 0.5, bounds.Top => 1.5 // bounds.Left => 0, bountd.Right => 2*pi double fvu = -2.0 * Math.PI / periodicBounds.Width; // "-", because toroidal surface needs it for correct orientation. What about NURBS? double fuv = 1.0 / periodicBounds.Height; toNonPeriodicBounds = new ModOp2D(fvu, 0, -fvu * periodicBounds.Left - Math.PI, 0, fuv, -fuv * periodicBounds.Bottom + 0.5); } } else if (periodicSurface.IsVPeriodic) { fullPeriod = true; double[] su = periodicSurface.GetUSingularities(); if (su != null && su.Length > 1) { List <double> lsu = new List <double>(su); for (int i = lsu.Count - 1; i >= 0; --i) { if (lsu[i] < periodicBounds.Left || lsu[i] > periodicBounds.Right) { lsu.RemoveAt(i); } } su = lsu.ToArray(); } if (su != null && su.Length > 0) { if (su.Length == 1) { hasPole = true; if (su[0] == periodicBounds.Left) { double fvu = 2.0 * Math.PI / periodicBounds.Height; double fuv = 1.0 / periodicBounds.Width; toNonPeriodicBounds = new ModOp2D(0, fvu, -fvu * periodicBounds.Bottom, fuv, 0, -fuv * periodicBounds.Left); } else if (su[0] == periodicBounds.Right) { double fvu = 2.0 * Math.PI / periodicBounds.Height; double fuv = 1.0 / periodicBounds.Width; toNonPeriodicBounds = new ModOp2D(0, -fvu, fvu * periodicBounds.Top, fuv, 0, -fuv * periodicBounds.Left); } else { throw new ApplicationException("pole must be on border"); } } else { throw new ApplicationException("more than one pole"); } } else { double fvu = 2.0 * Math.PI / periodicBounds.Height; double fuv = 1.0 / periodicBounds.Width; toNonPeriodicBounds = new ModOp2D(0, fvu, -fvu * periodicBounds.Bottom, fuv, 0, -fuv * periodicBounds.Left + 0.5); } } else { // not periodic, only pole removal // map the "periodic" parameter (where there is a singularity) onto [0..pi/2], the other parameter to [0..1] bool done = false; double[] su = periodicSurface.GetUSingularities(); if (su != null && su.Length == 1) { // the "period" to be resolved is in v, when u==su[0] you can change v and the point stays fixed hasPole = true; if (Math.Abs(su[0] - periodicBounds.Left) < periodicBounds.Width * 1e-6) { // we have to map the v interval of the periodic surface onto [0..pi/2] and the u interval onto [0..1] // and we also have to exchange u and v, so the non periodic bounds are [0..pi/2] in u and [0..1] in v double fvu = Math.PI / 2.0 / periodicBounds.Height; // tested: ok double fuv = 1.0 / periodicBounds.Width; toNonPeriodicBounds = new ModOp2D(0, fvu, -fvu * periodicBounds.Bottom, fuv, 0, -fuv * periodicBounds.Left); } else if (Math.Abs(su[0] - periodicBounds.Right) < periodicBounds.Width * 1e-6) { // here we additionally have tor reverse the v interval double fvu = Math.PI / 2.0 / periodicBounds.Height; // tested: ok double fuv = 1.0 / periodicBounds.Width; toNonPeriodicBounds = new ModOp2D(0, -fvu, fvu * periodicBounds.Top, -fuv, 0, fuv * periodicBounds.Right); } else { throw new ApplicationException("the pole must be on the border of the bounds"); } done = true; } if (!done) { double[] sv = periodicSurface.GetVSingularities(); if (sv != null && sv.Length == 1) { // the "period" to be resolved is in u hasPole = true; if (Math.Abs(sv[0] - periodicBounds.Bottom) < periodicBounds.Height * 1e-6) { // we have to map the u interval of the periodic surface onto [0..pi/2] and the v interval onto [0..1] double fvu = Math.PI / 2.0 / periodicBounds.Width; // tested: ok double fuv = 1.0 / periodicBounds.Height; toNonPeriodicBounds = new ModOp2D(-fvu, 0, fvu * periodicBounds.Right, 0, fuv, -fuv * periodicBounds.Bottom); } else if (Math.Abs(sv[0] - periodicBounds.Top) < periodicBounds.Height * 1e-6) { double fvu = Math.PI / 2.0 / periodicBounds.Width; // tested: ok double fuv = 1.0 / periodicBounds.Height; toNonPeriodicBounds = new ModOp2D(fvu, 0, -fvu * periodicBounds.Left, 0, -fuv, fuv * periodicBounds.Top); } else { throw new ApplicationException("the pole must be on the border of the bounds"); } done = true; } } if (!done) { throw new ApplicationException("there must be a single pole on the border of the bounds"); } } toPeriodicBounds = toNonPeriodicBounds.GetInverse(); #if DEBUG //GeoObjectList dbg = this.DebugGrid; //GeoObjectList dbgp = (this.periodicSurface as ISurfaceImpl).DebugGrid; #endif }
public override bool SameGeometry(BoundingRect thisBounds, ISurface other, BoundingRect otherBounds, double precision, out ModOp2D firstToSecond) { if (other is CylindricalSurfaceNP cnp) { if (Geometry.DistPL(cnp.location, location, zAxis) < precision && Geometry.DistPL(cnp.location + cnp.zAxis, location, zAxis) < precision) { firstToSecond = ModOp2D.Null; return(true); } firstToSecond = ModOp2D.Null; return(false); } return(base.SameGeometry(thisBounds, other, otherBounds, precision, out firstToSecond)); }