Exemple #1
0
        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);
        }