private static IEnumerable <IPdfPathItem> ConvertPolyline(DxfLwPolyline lwPolyline, DxfLayer layer, Matrix4 affine, Matrix4 scale) { var pdfStreamState = new PdfStreamState( strokeColor: GetPdfColor(lwPolyline, layer), strokeWidth: GetStrokeWidth(lwPolyline, layer)); IList <DxfLwPolylineVertex> vertices = lwPolyline.Vertices; int n = vertices.Count; DxfLwPolylineVertex vertex = vertices[0]; for (int i = 1; i < n; i++) { DxfLwPolylineVertex next = vertices[i]; yield return(ConvertPolylineSegment(vertex, next, affine, scale, pdfStreamState)); vertex = next; } if (lwPolyline.IsClosed) { var next = vertices[0]; var p1 = affine.Transform(new Vector(vertex.X, vertex.Y, 0)) .ToPdfPoint(PdfMeasurementType.Point); var p2 = affine.Transform(new Vector(next.X, next.Y, 0)) .ToPdfPoint(PdfMeasurementType.Point); yield return(new PdfLine(p1, p2, pdfStreamState)); } }
/// <summary> /// Convert a Vector3 to a DXF Lightweight Polyline Vertex. /// </summary> public static DxfLwPolylineVertex ToDxfLwPolylineVertex(this Vector3 vector3) { var vertex = new DxfLwPolylineVertex(); vertex.X = vector3.X; vertex.Y = vector3.Y; return(vertex); }
private static IPdfPathItem ConvertPolylineSegment(DxfLwPolylineVertex vertex, DxfLwPolylineVertex next, Matrix4 affine, Matrix4 scale, PdfStreamState pdfStreamState) { var p1 = affine.Transform(new Vector(vertex.X, vertex.Y, 0)) .ToPdfPoint(PdfMeasurementType.Point); var p2 = affine.Transform(new Vector(next.X, next.Y, 0)) .ToPdfPoint(PdfMeasurementType.Point); if (vertex.Bulge.Equals(0.0)) { return(new PdfLine(p1, p2, pdfStreamState)); } double dx = next.X - vertex.X; double dy = next.Y - vertex.Y; double length = Math.Sqrt(dx * dx + dy * dy); if (length <= 1e-10) { // segment is very short, avoid numerical problems return(new PdfLine(p1, p2, pdfStreamState)); } double alpha = 4.0 * Math.Atan(vertex.Bulge); double radius = length / (2.0 * Math.Abs(Math.Sin(alpha * 0.5))); double bulgeFactor = Math.Sign(vertex.Bulge) * Math.Cos(alpha * 0.5) * radius; double normalX = -(dy / length) * bulgeFactor; double normalY = +(dx / length) * bulgeFactor; // calculate center (dxf coordinate system), start and end angle double cx = (vertex.X + next.X) / 2 + normalX; double cy = (vertex.Y + next.Y) / 2 + normalY; double startAngle; double endAngle; if (vertex.Bulge > 0) // counter-clockwise { startAngle = Math.Atan2(vertex.Y - cy, vertex.X - cx); endAngle = Math.Atan2(next.Y - cy, next.X - cx); } else // clockwise: flip start and end angle { startAngle = Math.Atan2(next.Y - cy, next.X - cx); endAngle = Math.Atan2(vertex.Y - cy, vertex.X - cx); } // transform to PDF coordinate system var center = affine.Transform(new Vector(cx, cy, 0)).ToPdfPoint(PdfMeasurementType.Point); var pdfRadius = scale.Transform(new Vector(radius, radius, radius)).ToPdfPoint(PdfMeasurementType.Point); const double rotation = 0; return(new PdfEllipse(center, pdfRadius.X, pdfRadius.Y, rotation, startAngle, endAngle, pdfStreamState)); }
private static SvgPathSegment FromPolylineVertices(DxfLwPolylineVertex last, DxfLwPolylineVertex next) { var dx = next.X - last.X; var dy = next.Y - last.Y; var dist = Math.Sqrt(dx * dx + dy * dy); if (last.Bulge == 0.0 || IsCloseTo(dist, 1.0e-10)) { // line or a really short arc return(new SvgLineToPath(next.X, next.Y)); } // given the following diagram: // // p1 // -) // - | ) // - | ) // - | ) // O ------------|C----T // - | ) // - | ) // - | ) // -) // p2 // // where O is the center of the circle, C is the midpoint between p1 and p2, calculate // the hypotenuse of the triangle Op1C to get the radius var includedAngle = Math.Atan(Math.Abs(last.Bulge)) * 4.0; var isLargeArc = includedAngle > Math.PI; var isCounterClockwise = last.Bulge > 0.0; // find radius var oppositeLength = dist / 2.0; var radius = oppositeLength / Math.Sin(includedAngle / 2.0); return(new SvgArcToPath(radius, radius, 0.0, isLargeArc, isCounterClockwise, next.X, next.Y)); }
private float Distance(DxfLwPolylineVertex p1, DxfLwPolylineVertex p2) { return((float)Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y))); }
public static Vertex ToVertex(this DxfLwPolylineVertex vertex, double elevation) { return(VertexFromPointAndBulge(new Point(vertex.X, vertex.Y, elevation), vertex.Bulge)); }
public completeDxfStruct processDxfFile(string in_obtainedFileName) { completeDxfStruct valueToReturn = new completeDxfStruct(); DxfFile dxfFile; using (System.IO.FileStream fs = new System.IO.FileStream(in_obtainedFileName, System.IO.FileMode.Open)) { dxfFile = DxfFile.Load(fs); IList <DxfBlock> allBlocks = dxfFile.Blocks; IList <DxfEntity> usedEntities; if ((allBlocks.Count == 0) || (allBlocks[0].Name.ToUpper().Contains("MODEL") == false)) { usedEntities = dxfFile.Entities; } else { usedEntities = allBlocks[0].Entities; } foreach (DxfEntity entity in dxfFile.Entities) { switch (entity.EntityType) { case DxfEntityType.Line: { DxfLine line = (DxfLine)entity; MyDxfLine TransfLine = new MyDxfLine(line.P1.X, line.P1.Y, line.P2.X, line.P2.Y); valueToReturn.addDxfDrawingEntry(TransfLine); break; } case DxfEntityType.Arc: { DxfArc arc = (DxfArc)entity; MyDxfArc TransfArc = new MyDxfArc(arc.Center.X, arc.Center.Y, arc.StartAngle, arc.EndAngle, arc.Radius); valueToReturn.addDxfDrawingEntry(TransfArc); break; } case DxfEntityType.LwPolyline: { //polyline. It has vertices. DxfLwPolyline polylineS = entity as DxfLwPolyline; int totalnumberOfVertices = polylineS.Vertices.Count; for (int i = 0; i < totalnumberOfVertices - 1; i++) { //iterate through vertices, taking them by 2. A figure is between these two DxfLwPolylineVertex point1 = polylineS.Vertices[i]; DxfLwPolylineVertex point2 = polylineS.Vertices[i + 1]; if (point1.Bulge == 0) { MyDxfLine TransfLine = new MyDxfLine(point1.X, point1.Y, point2.X, point2.Y); valueToReturn.addDxfDrawingEntry(TransfLine); } else //it is arc // The bulge is the tangent of one fourth the included angle for an arc segment, // made negative if the arc goes clockwise from the start point to the endpoint. // A bulge of 0 indicates a straight segment, and a bulge of 1 is a semicircle { double angleOfArc = System.Math.Atan(point1.Bulge) * 180.0 / Math.PI * 4; double startAngle = Math.Atan(point1.Y / point1.X) * 180.0 / Math.PI; //double endAngle = } } break; } case DxfEntityType.Polyline: { //https://github.com/IxMilia/Dxf/issues/90 DxfPolyline polyline = entity as DxfPolyline; break; } } } } return(valueToReturn); }
private static SvgPathSegment FromPolylineVertices(DxfLwPolylineVertex last, DxfLwPolylineVertex next) { return(FromVertices(new Tuple <double, double>(last.X, last.Y), new Tuple <double, double>(next.X, next.Y), last.Bulge)); }
private static SvgPathSegment FromPolylineVertices(DxfLwPolylineVertex last, DxfLwPolylineVertex next) { return(FromPolylineVertices(last.X, last.Y, last.Bulge, next.X, next.Y)); }
/// <summary> /// Parse DXF into VectorShape list. /// </summary> public static List <VectorShape> ReadDXF(Stream dxfStream) { List <VectorShape> shapes = new List <VectorShape>(); DxfFile dxfFile = DxfFile.Load(dxfStream); Dictionary <string, Color32> layerColors = new Dictionary <string, Color32>(); foreach (DxfLayer layer in dxfFile.Layers) { layerColors.Add(layer.Name, ConvertColor(layer.Color)); } foreach (DxfEntity entity in dxfFile.Entities) { VectorShape shape = null; switch (entity.EntityType) { case DxfEntityType.Point: DxfModelPoint point = entity as DxfModelPoint; shape = new PointShape(ConvertPoint(point.Location)); break; case DxfEntityType.Line: DxfLine line = entity as DxfLine; Vector2[] endpoints = new Vector2[2]; endpoints[0] = ConvertPoint(line.P1); endpoints[1] = ConvertPoint(line.P2); shape = new PolyShape(endpoints); break; case DxfEntityType.Spline: DxfSpline spline = entity as DxfSpline; if ((spline.NumberOfControlPoints % spline.DegreeOfCurve) != 1) { Debug.LogError("Invalid spline data! Wrong number of points. " + spline); break; } Vector2[] controlPoints = new Vector2[spline.NumberOfControlPoints]; for (int i = 0; i < controlPoints.Length; i++) { controlPoints[i] = ConvertPoint(spline.ControlPoints[i]); } shape = new PolyShape(controlPoints[0]); PolyShape shapeSpline = shape as PolyShape; switch (spline.DegreeOfCurve) { case 1: for (int i = 1; i < controlPoints.Length; i++) { shapeSpline.LineTo(controlPoints[i]); } break; case 2: for (int i = 1; i < controlPoints.Length; i += 2) { shapeSpline.CurveTo(controlPoints[i + 1], controlPoints[i]); } break; case 3: for (int i = 1; i < controlPoints.Length; i += 3) { shapeSpline.CurveTo(controlPoints[i + 2], controlPoints[i], controlPoints[i + 1]); } break; default: Debug.LogWarning("Spline with unsupported curve of degree: " + spline.DegreeOfCurve); break; } break; case DxfEntityType.Arc: DxfArc arc = entity as DxfArc; // If the arc is a complete circle just make one of those float startAngle = (float)arc.StartAngle; while (startAngle < 0f) { startAngle += 360f; } float endAngle = (float)arc.EndAngle; while (endAngle < startAngle) { endAngle += 360f; } float sweep = endAngle - startAngle; shape = new CircleShape(ConvertPoint(arc.Center), (float)arc.Radius, startAngle, sweep); break; case DxfEntityType.Circle: DxfCircle circle = entity as DxfCircle; shape = new CircleShape(ConvertPoint(circle.Center), (float)circle.Radius * dxfScale); break; case DxfEntityType.Ellipse: DxfEllipse ellipse = entity as DxfEllipse; // If the ellipse is actually a circle just make one of those if (Mathf.Approximately((float)ellipse.MinorAxisRatio, 1f)) { shape = new CircleShape(ConvertPoint(ellipse.Center), (float)ellipse.MajorAxis.Length * dxfScale); } else { shape = new EllipseShape(ConvertPoint(ellipse.Center), ConvertVector(ellipse.MajorAxis), (float)ellipse.MinorAxisRatio); } break; case DxfEntityType.Polyline: DxfPolyline polyline = entity as DxfPolyline; if (polyline.ContainsVertices) { Vector2[] vertices = new Vector2[polyline.Vertices.Count]; for (int i = 0; i < vertices.Length; i++) { vertices[i] = ConvertPoint(polyline.Vertices[i].Location); } shape = new PolyShape(vertices[0]); PolyShape shapePolyline = shape as PolyShape; for (int i = 1; i < vertices.Length; i++) { float bulge = (float)polyline.Vertices[i - 1].Bulge; shapePolyline.ArcToDXF(vertices[i], bulge); } if (polyline.IsClosed) { float bulge = (float)polyline.Vertices[vertices.Length - 1].Bulge; shapePolyline.ArcToDXF(vertices[0], bulge); shape.Closed = true; } } break; case DxfEntityType.LwPolyline: { DxfLwPolyline lwPolyline = entity as DxfLwPolyline; Vector2[] vertices = new Vector2[lwPolyline.Vertices.Count]; for (int i = 0; i < vertices.Length; i++) { DxfLwPolylineVertex lwpVertex = lwPolyline.Vertices[i]; vertices[i] = ConvertPoint(lwpVertex.X, lwpVertex.Y); } shape = new PolyShape(vertices[0]); PolyShape shapePolyline = shape as PolyShape; for (int i = 1; i < vertices.Length; i++) { float bulge = (float)lwPolyline.Vertices[i - 1].Bulge; shapePolyline.ArcToDXF(vertices[i], bulge); } if (lwPolyline.IsClosed) { float bulge = (float)lwPolyline.Vertices[vertices.Length - 1].Bulge; shapePolyline.ArcToDXF(vertices[0], bulge); shape.Closed = true; } } break; default: Debug.Log("Unhandled entity of type: " + entity.EntityType); break; } if (shape != null) { if (entity.IsVisible) { Color32 shapeColor = ConvertColor(entity.Color); //layerColors.TryGetValue(entity.Layer, out shapeColor); shape.colorOutline = shapeColor; shapes.Add(shape); } } } return(shapes); }
public static completeDxfStruct processDxfFile(string in_obtainedFileName) { completeDxfStruct valueToReturn = new completeDxfStruct(); DxfFile dxfFile; using (System.IO.FileStream fs = new System.IO.FileStream(in_obtainedFileName, System.IO.FileMode.Open)) { dxfFile = DxfFile.Load(fs); IList <DxfBlock> allBlocks = dxfFile.Blocks; IList <DxfEntity> usedEntities; if ((allBlocks.Count == 0) || (allBlocks[0].Name.ToUpper().Contains("MODEL") == false)) { usedEntities = dxfFile.Entities; } else { usedEntities = allBlocks[0].Entities; } foreach (DxfEntity entity in dxfFile.Entities) { switch (entity.EntityType) { case DxfEntityType.Line: { DxfLine line = (DxfLine)entity; MyDxfLine TransfLine = new MyDxfLine(line.P1.X, line.P1.Y, line.P2.X, line.P2.Y, line.Layer); valueToReturn.addDxfDrawingEntry(TransfLine); break; } case DxfEntityType.Arc: { DxfArc arc = (DxfArc)entity; MyDxfArc TransfArc = new MyDxfArc(arc.Center.X, arc.Center.Y, arc.StartAngle, arc.EndAngle, arc.Radius, arc.Layer); valueToReturn.addDxfDrawingEntry(TransfArc); break; } case DxfEntityType.LwPolyline: { //polyline. It has vertices. DxfLwPolyline polylineS = entity as DxfLwPolyline; int totalnumberOfVertices = polylineS.Vertices.Count; for (int i = 0; i < totalnumberOfVertices - 1; i++) { //iterate through vertices, taking them by 2. A figure is between these two DxfLwPolylineVertex point1 = polylineS.Vertices[i]; DxfLwPolylineVertex point2 = polylineS.Vertices[i + 1]; if (point1.Bulge == 0) { MyDxfLine TransfLine = new MyDxfLine(point1.X, point1.Y, point2.X, point2.Y, polylineS.Layer); valueToReturn.addDxfDrawingEntry(TransfLine); } else //it is arc // The bulge is the tangent of one fourth the included angle for an arc segment, // made negative if the arc goes clockwise from the start point to the endpoint. // A bulge of 0 indicates a straight segment, and a bulge of 1 is a semicircle { double angleOfArcRad = System.Math.Atan(Math.Abs(point1.Bulge)) * 4; // http://mymathforum.com/algebra/21368-find-equation-circle-given-two-points-arc-angle.html // tides of Internet have almost washed this post in forum double xA; double xB; double yA; double yB; if (point1.Bulge < 0) { xA = point2.X; yA = point2.Y; xB = point1.X; yB = point1.Y; } else { xA = point1.X; yA = point1.Y; xB = point2.X; yB = point2.Y; } double d_square = (xA - xB) * (xA - xB) + (yA - yB) * (yA - yB); double r_square = (d_square) / (2.0 * (1.0 - Math.Cos(angleOfArcRad))); double m = (xA - xB) / (yB - yA); double a = Math.Sqrt(r_square - d_square / 4.0); double xM = (xA + xB) / 2.0; double yM = (yA + yB) / 2.0; double xC_plus = xM + a / Math.Sqrt(m * m + 1); double xC_minus = xM - a / Math.Sqrt(m * m + 1); double yC_plus = yM + m * a / Math.Sqrt(m * m + 1); double yC_minus = yM - m * a / Math.Sqrt(m * m + 1); // https://en.wikipedia.org/wiki/Linear_equation#Point%E2%80%93slope_form double usedXCenter; double usedYCenter; double usedAngle1; double usedAngle2; // https://stackoverflow.com/questions/1311049/how-to-map-atan2-to-degrees-0-360 double angle1_candidate1 = (Math.Atan2(yA - yC_plus, xA - xC_plus) * 180 / Math.PI + 360) % 360; double angle2_candidate1 = (Math.Atan2(yB - yC_plus, xB - xC_plus) * 180 / Math.PI + 360) % 360; double angle1_candidate2 = (Math.Atan2(yA - yC_minus, xA - xC_minus) * 180 / Math.PI + 360) % 360; double angle2_candidate2 = (Math.Atan2(yB - yC_minus, xB - xC_minus) * 180 / Math.PI + 360) % 360; //mydxfarc expects angles counterclockwise if (point1.Bulge > 0) { if (angle1_candidate1 < angle2_candidate1) { usedAngle1 = angle1_candidate1; usedAngle2 = angle2_candidate1; usedXCenter = xC_plus; usedYCenter = yC_plus; } else { usedAngle1 = angle1_candidate2; usedAngle2 = angle2_candidate2; usedXCenter = xC_minus; usedYCenter = yC_minus; } } else { if (angle1_candidate1 > angle2_candidate1) { usedAngle1 = angle1_candidate2; usedAngle2 = angle2_candidate2; usedXCenter = xC_minus; usedYCenter = yC_minus; } else { usedAngle1 = angle1_candidate1; usedAngle2 = angle2_candidate1; usedXCenter = xC_plus; usedYCenter = yC_plus; } } MyDxfArc TransfArc = new MyDxfArc(usedXCenter, usedYCenter, usedAngle1, usedAngle2, Math.Sqrt(r_square), polylineS.Layer); valueToReturn.addDxfDrawingEntry(TransfArc); } } if (polylineS.IsClosed) { DxfLwPolylineVertex point1 = polylineS.Vertices[totalnumberOfVertices - 1]; DxfLwPolylineVertex point2 = polylineS.Vertices[0]; if (point1.Bulge == 0) { MyDxfLine TransfLine = new MyDxfLine(point1.X, point1.Y, point2.X, point2.Y, polylineS.Layer); valueToReturn.addDxfDrawingEntry(TransfLine); } else // arc // I so like the code above, so I cannot resist to copypaste it { double angleOfArcRad = System.Math.Atan(Math.Abs(point1.Bulge)) * 4; double xA; double xB; double yA; double yB; if (point1.Bulge < 0) { xA = point2.X; yA = point2.Y; xB = point1.X; yB = point1.Y; } else { xA = point1.X; yA = point1.Y; xB = point2.X; yB = point2.Y; } double d_square = (xA - xB) * (xA - xB) + (yA - yB) * (yA - yB); double r_square = (d_square) / (2.0 * (1.0 - Math.Cos(angleOfArcRad))); double m = (xA - xB) / (yB - yA); double a = Math.Sqrt(r_square - d_square / 4.0); double xM = (xA + xB) / 2.0; double yM = (yA + yB) / 2.0; double xC_plus = xM + a / Math.Sqrt(m * m + 1); double xC_minus = xM - a / Math.Sqrt(m * m + 1); double yC_plus = yM + m * a / Math.Sqrt(m * m + 1); double yC_minus = yM - m * a / Math.Sqrt(m * m + 1); // https://en.wikipedia.org/wiki/Linear_equation#Point%E2%80%93slope_form double usedXCenter; double usedYCenter; double usedAngle1; double usedAngle2; // https://stackoverflow.com/questions/1311049/how-to-map-atan2-to-degrees-0-360 double angle1_candidate1 = (Math.Atan2(yA - yC_plus, xA - xC_plus) * 180 / Math.PI + 360) % 360; double angle2_candidate1 = (Math.Atan2(yB - yC_plus, xB - xC_plus) * 180 / Math.PI + 360) % 360; double angle1_candidate2 = (Math.Atan2(yA - yC_minus, xA - xC_minus) * 180 / Math.PI + 360) % 360; double angle2_candidate2 = (Math.Atan2(yB - yC_minus, xB - xC_minus) * 180 / Math.PI + 360) % 360; //mydxfarc expects angles counterclockwise if (point1.Bulge > 0) { if (angle1_candidate1 < angle2_candidate1) { usedAngle1 = angle1_candidate1; usedAngle2 = angle2_candidate1; usedXCenter = xC_plus; usedYCenter = yC_plus; } else { usedAngle1 = angle1_candidate2; usedAngle2 = angle2_candidate2; usedXCenter = xC_minus; usedYCenter = yC_minus; } } else { if (angle1_candidate1 > angle2_candidate1) { usedAngle1 = angle1_candidate2; usedAngle2 = angle2_candidate2; usedXCenter = xC_minus; usedYCenter = yC_minus; } else { usedAngle1 = angle1_candidate1; usedAngle2 = angle2_candidate1; usedXCenter = xC_plus; usedYCenter = yC_plus; } } MyDxfArc TransfArc = new MyDxfArc(usedXCenter, usedYCenter, usedAngle1, usedAngle2, Math.Sqrt(r_square), polylineS.Layer); valueToReturn.addDxfDrawingEntry(TransfArc); } } break; } case DxfEntityType.Polyline: { //this is a spawn of autocad. Either copypaste code from LwPolyline section. Or just save the file in QCad. //QCad replaces all polylines by lwPolylines //https://github.com/IxMilia/Dxf/issues/90 DxfPolyline polyline = entity as DxfPolyline; break; } } } } return(valueToReturn); }