/// <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); }
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)); } }
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 } }