/// <summary> /// Setup only INITIAL logical and graphical datastructures. /// </summary> /// <param name="in_savedStructureOfDxf">Logical structure of DXF as read from file</param> public void setupLogicalAndGraphicalDXFstructures(LOGICAL.completeDxfStruct in_savedStructureOfDxf) { savedStructureOfDxf = in_savedStructureOfDxf; //generate primal drawing structure MyDxfBoundingBox obtainedBox2 = savedStructureOfDxf.GetBoundingBox(); if (obtainedBox2.XLowerLeft != 0) { offsetOfDxfHorizontal = 0 - obtainedBox2.XLowerLeft; } if (obtainedBox2.YLowerLeft != 0) { offsetOfDxfVertical = 0 - obtainedBox2.YLowerLeft; } primalDrawingStructure = new CompleteDxfDrawingStruct(null); int currentSizeOfDxfStruct = savedStructureOfDxf.getSize(); for (int i = 0; i < currentSizeOfDxfStruct; i++) { DXFdrawingEntry someEntry = savedStructureOfDxf.getItemByIndex(i); MyDxfBoundingBox obtainedBox = someEntry.GetBoundingBox(); //offsets to centralize the drawing in the box Pen usedPen = null; if ((collectionOfLayerDefinitions != null) && (collectionOfLayerDefinitions.ContainsKey(someEntry.layerIdentifier))) { usedPen = collectionOfLayerDefinitions[someEntry.layerIdentifier].Item2; } else { usedPen = new Pen(Color.Black); } if (someEntry is MyDxfLine) { MyDxfLine castLine = someEntry as MyDxfLine; DXFentryForDisplay theLineForDisplay = new MyDxfLineForDisplay(castLine.XStart + offsetOfDxfHorizontal, castLine.YStart + offsetOfDxfVertical, castLine.XEnd + offsetOfDxfHorizontal, castLine.YEnd + offsetOfDxfVertical, usedPen); primalDrawingStructure.addSingleEntry(theLineForDisplay, obtainedBox.XLowerLeft + offsetOfDxfHorizontal, obtainedBox.YLowerLeft + offsetOfDxfVertical, obtainedBox.XUpperRight + offsetOfDxfHorizontal, obtainedBox.YUpperRight + offsetOfDxfVertical); } else if (someEntry is MyDxfArc) { MyDxfArc castArc = someEntry as MyDxfArc; DXFentryForDisplay theArcForDisplay = new MyDxfArcForDisplay(castArc.XCenter + offsetOfDxfHorizontal, castArc.YCenter + offsetOfDxfVertical, castArc.Radius, castArc.StartAngleDegree, castArc.EndAngleDegree, usedPen); primalDrawingStructure.addSingleEntry(theArcForDisplay, obtainedBox.XLowerLeft + offsetOfDxfHorizontal, obtainedBox.YLowerLeft + offsetOfDxfVertical, obtainedBox.XUpperRight + offsetOfDxfHorizontal, obtainedBox.YUpperRight + offsetOfDxfVertical); } } //performing flip on draw structure is done by means of graphical container }
public static void exportCompleteDrawingStructToWMF(string in_pathToWMFFile, double in_scalefactor, DXFRendering.LOGICAL.completeDxfStruct in_dxfStruct) { MyDxfBoundingBox theBoundingBox = in_dxfStruct.GetBoundingBox(); double bitmapInitialWidth = Math.Abs(theBoundingBox.XLowerLeft - theBoundingBox.XUpperRight); double bitmapInitialHeight = Math.Abs(theBoundingBox.YLowerLeft - theBoundingBox.YUpperRight); //you know, dxf file might not be located at 0; 0 as lower Left. So I apply movement coefficients double unscaledOffsetX = theBoundingBox.XLowerLeft; double unscaledOffsetY = theBoundingBox.YLowerLeft; double newWidthPrescaled = in_scalefactor * bitmapInitialWidth; double newHeightPrescaled = in_scalefactor * bitmapInitialHeight; int wdth = (int)Math.Ceiling(newWidthPrescaled) + 1; int hght = (int)Math.Ceiling(newHeightPrescaled) + 1; var wmf = new WmfDocument(); wmf.Width = wdth; wmf.Height = hght; //https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wmf/828e1864-7fe7-42d8-ab0a-1de161b32f27 // 1440 ? wmf.Format.Unit = 288; wmf.AddCreatePenIndirect(Color.Black, PenStyle.PS_SOLID, 1); //0: generic pen, black wmf.AddCreatePenIndirect(Color.Red, PenStyle.PS_SOLID, 1); //1: PVC pen, red wmf.AddCreatePenIndirect(Color.Blue, PenStyle.PS_SOLID, 1); //2: ALU pen, blue wmf.AddCreatePenIndirect(Color.Yellow, PenStyle.PS_SOLID, 1); //3: EXT Prof pen, yellow wmf.AddCreatePenIndirect(Color.Orange, PenStyle.PS_SOLID, 1); //4: Thermic bridge pen, orange int allElementsLength = in_dxfStruct.getSize(); // similar to prepareGraphicalDataStruct for (int i = 0; i < allElementsLength; i++) { DXFRendering.LOGICAL.DXFdrawingEntry someEntry = in_dxfStruct.getItemByIndex(i); // I use y candidates to perform flipping vertically. It is possible to redirect Y axy, but that WMF entry is barely supported if (someEntry is DXFRendering.LOGICAL.MyDxfLine) { MyDxfLine lineEntry = someEntry as MyDxfLine; int indx = getindexOfPenByLayerName(lineEntry.layerIdentifier); if (indx >= 0) { wmf.AddSelectObject(indx); int y1candidate = (int)Math.Ceiling((lineEntry.YStart - unscaledOffsetY) * in_scalefactor); int y2candidate = (int)Math.Ceiling((lineEntry.YEnd - unscaledOffsetY) * in_scalefactor); wmf.AddLine( new Point( (int)Math.Ceiling((lineEntry.XStart - unscaledOffsetX) * in_scalefactor), -y1candidate + hght), new Point( (int)Math.Ceiling((lineEntry.XEnd - unscaledOffsetX) * in_scalefactor), -y2candidate + hght) ); } } else if (someEntry is DXFRendering.LOGICAL.MyDxfArc) { DXFRendering.LOGICAL.MyDxfArc castArc = someEntry as DXFRendering.LOGICAL.MyDxfArc; //https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wmf/742097b4-5879-4c36-b57e-77e7cc152253 int indx = getindexOfPenByLayerName(castArc.layerIdentifier); if (indx >= 0) { wmf.AddSelectObject(indx); int yRectangleCandidate = (int)Math.Ceiling((castArc.YCenter - castArc.Radius - unscaledOffsetY) * in_scalefactor); int dimCandidate = (int)Math.Ceiling(2 * castArc.Radius * in_scalefactor); Rectangle boundRectangle = new Rectangle( (int)Math.Ceiling((castArc.XCenter - castArc.Radius - unscaledOffsetX) * in_scalefactor), -yRectangleCandidate + hght - dimCandidate, dimCandidate, dimCandidate); int yPnt1Candidate = (int)Math.Ceiling((castArc.YCenter + castArc.Radius * Math.Sin(castArc.StartAngleRad) - unscaledOffsetY) * in_scalefactor); Point pnt1 = new Point( (int)Math.Ceiling((castArc.XCenter + castArc.Radius * Math.Cos(castArc.StartAngleRad) - unscaledOffsetX) * in_scalefactor), -yPnt1Candidate + hght ); int yPnt2Candidate = (int)Math.Ceiling((castArc.YCenter + castArc.Radius * Math.Sin(castArc.EndAngleRad) - unscaledOffsetY) * in_scalefactor); Point pnt2 = new Point( (int)Math.Ceiling((castArc.XCenter + castArc.Radius * Math.Cos(castArc.EndAngleRad) - unscaledOffsetX) * in_scalefactor), -yPnt2Candidate + hght ); wmf.AddArc(boundRectangle, pnt1, pnt2); /* * wmf.AddRectangle(boundRectangle); * wmf.AddSelectObject(3); * wmf.AddLine(pnt1, pnt2); */ } } } wmf.AddDeleteObject(0); wmf.AddDeleteObject(1); wmf.AddDeleteObject(2); wmf.AddDeleteObject(3); wmf.AddDeleteObject(4); wmf.Save(in_pathToWMFFile); }
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); }