cart: empty [ Login ]

how to get a sequence of coordinates

1 
momic
4/30/2013 1:09 PM
hi, I have a DWG file that contains a 2D Shape, this shape maybe built whit multiple entities like ARC , SPLINE, POLYLINES etc. I would like to extract points's coordinates in the correct sequence(clockwise or counterclockwise) because this sequence will be used by a cutting machine. Please see the shape in attached file,i have two problems: 1) The shape's entity are mixed ( sequence ) 2) Some arcs are constructed in counterclockwise while others clockwise. Is it possible to obtain something like a path? how can I solve this problem? thanks in advance!!!
Optimise-IT
5/8/2013 4:22 PM
I read in another post here that there isn't any particular order to the entities in a dxf/dwg file. I have the same problem and plan to solve it by comparing start and end coordinates of all entities and making the shapes myself.
rammi
5/10/2013 11:42 AM
In this generality it is probably best if you roll your own IWireframeGraphicsFactory, and make use of CadLib to handle the different entities correctly. This is not as hard as it seems. Here is an example implementation which may already fit your needs:
C# Code:
/// <summary> /// Specialized wireframe graphics factory which converts path data to 2D polylines. /// </summary> /// <remarks> /// Texts, points, rays, xlines and images are ignored. /// </remarks> public class PolygonWireframeGraphicsFactory : IWireframeGraphicsFactory { private readonly List<Polyline2D> collectedPolylines = new List<Polyline2D>(); /// <summary> /// Convert the relevant part of a model to polylines. /// </summary> /// <reamrks> /// The polylines are sorted in drawing order. /// </reamrks> /// <param name="model">The model.</param> /// <param name="graphicsConfig">Graphics configuration, useful for tuning accuracy</param> /// <returns>List of polylines.</returns> public static List<Polyline2D> ConvertModelToPolylines(DxfModel model, GraphicsConfig graphicsConfig) { DrawContext.Wireframe wireframe = new DrawContext.Wireframe.ModelSpace(model, graphicsConfig, Matrix4D.Identity); PolygonWireframeGraphicsFactory factory = new PolygonWireframeGraphicsFactory(); model.Draw(wireframe, factory); return factory.collectedPolylines; } #region IWireframeGraphicsFactory Implementation public void BeginEntity(DxfEntity entity, DrawContext.Wireframe drawContext) { // ignored } public void EndEntity() { // ignored } public void BeginInsert(DxfInsert insert) { // ignore } public void EndInsert() { // ignore } public void CreateDot(DxfEntity entity, DrawContext.Wireframe drawContext, ArgbColor color, bool forText, Vector4D position) { // ignore point } public void CreateLine(DxfEntity entity, DrawContext.Wireframe drawContext, ArgbColor color, bool forText, Vector4D start, Vector4D end) { collectedPolylines.Add(new Polyline2D(start.ToPoint2D(), end.ToPoint2D())); } public void CreateRay(DxfEntity entity, DrawContext.Wireframe drawContext, ArgbColor color, Segment4D segment) { // ignore ray } public void CreateXLine(DxfEntity entity, DrawContext.Wireframe drawContext, ArgbColor color, Vector4D? startPoint, Segment4D segment) { // ignore xline } public void CreatePath(DxfEntity entity, DrawContext.Wireframe drawContext, ArgbColor color, bool forText, IList<Polyline4D> polylines, bool fill) { if (forText) { // should not happen, see SupportsText below return; } // maybe you want to ignore filled paths, too foreach (Polyline4D poly4d in polylines) { Polyline2D poly2d = new Polyline2D(poly4d.Count, poly4d.Closed); foreach (Vector4D v4d in poly4d) { poly2d.Add(v4d.ToPoint2D()); } collectedPolylines.Add(poly2d); } } public void CreatePathAsOne(DxfEntity entity, DrawContext.Wireframe drawContext, ArgbColor color, bool forText, IList<Polyline4D> polylines, bool fill) { // maybe you want to ignore these, too CreatePath(entity, drawContext, color, forText, polylines, fill); } public void CreateShape(DxfEntity entity, DrawContext.Wireframe drawContext, ArgbColor color, bool forText, IShape4D shape) { CreatePathAsOne(entity, drawContext, color, forText, shape.ToPolylines4D(), shape.IsFilled); } public bool SupportsText { get { return true; } // by returning true here only the text specific methods below will be use } public void CreateText(DxfText text, DrawContext.Wireframe drawContext, ArgbColor color) { // ignore text } public void CreateMText(DxfMText text, DrawContext.Wireframe drawContext) { // ignore text } public void CreateImage(DxfRasterImage rasterImage, DrawContext.Wireframe drawContext, Polyline4D clipPolygon, Polyline4D imageBoundary, Vector4D transformedOrigin, Vector4D transformedXAxis, Vector4D transformedYAxis) { // ignore images } #endregion }
The above class allows to convert the model space of a model to a list of 2D polylines by its static ConvertModelToPolylines() method. The resulting list is ordered like the entities from which the polylines were created are sorted in the file, and the lines may run in reversed direction. Polylines are easily compared by start and end point, easily reversed (GetReverse()), and it is not complicated to calculate their length (GetLength(). The latter would have been more complicated when based on IShape2D, which on the other hand would allow for more accuracy in some areas. The accuracy of the constructed polylines can be influenced by setting various properties of the GraphicsConfig passed to the conversion method. The resulting list will need reordering and probably reversion of some of the lines to create a complete boundary. Depending on the quality of your CAD files this may be quite challenging. When I did something similar for a customer years ago (in Java, based on a different lib), I had some problems because quite a lot files contained small gaps between entities which should have been connected. Even if your files are of better quality, you should not expect end and start points of different polylines to be exactly the same, as the floating point math under the hood will create small deviations. Detection of boundaries basically goes the following way:
  1. Remove all polylines from the list which are already explicitly closed or have the same start and end point and put them to your result list of closed boundaries.
  2. Remove the first polyline from the remaining list, and compare all others whether their start or end point matches either start or end point of the removed one. If you find a match, remove the matching line, connect it correctly with the test polyline, and check whether it closes the boundary. If yes, put it to the result list, and restart this step by removing the next first polyline until polyline list is empty, if no, restart comparing the whole list with the expanded polyline for start/end matches.
  3. If you run through w/o closing the line you have a problem, but you can put that line into a special problem list and continue with step 2.
For a small list of polylines the above algorithm is fast enough, although obviously in step 2 you'll do a lot of duplicate comparisions when expanding a polyline. If your basic list of polylines is large, performance can be enhanced a lot by using a more complex data structure where you sort your polylines by the X and Y coordinates of both their start and end points, which reduces the necessary number of comparisions by orders of magnitude, but makes bookkeeping complex, so for the beginning I'd avoid that. - Rammi
Ravi Magod
9/12/2015 10:30 AM
Hi I have basic understanding of VB, factory etc are slightly on higher side. I converted the above code to VB. I tried get list of Polyline2D by using Dim collectedPolylines As List(Of WW.Math.Geometry.Polyline2D) = PolygonWireframeGraphicsFactory.ConvertModelToPolylines(model, GraphicsConfig.BlackBackground) Console.WriteLine(String.Format("DxfEntity count - {0}. PolyLineCount - {1}", model.Entities.Count, collectedPolylines.Count)) I get the following result DxfEntity count - 230. PolyLineCount - 0 When I use another DXf in which the Drawing is converted to Polylines I get DxfEntity count - 50. PolyLineCount - 0 I have attached the DXF file Where am I going wrong. Regards Ravi Magod
Wout
9/12/2015 6:47 PM
The attachment is missing. - Wout
Ravi Magod
9/13/2015 7:34 AM
Hi Sorry, 2.5MM q4.Dxf Attached Ravi Magod
rammi
9/15/2015 12:34 PM
Hi Ravi, I still don't see the attachment. You can use the [SELECT FILES] button below the text input field for attaching files when writing your answer. - Rammi
Wout
9/15/2015 1:06 PM
The code is a bit outdated because this is an old forum post. The IWireframeGraphicsFactory has changed a little. The new code is:
C# Code:
/// <summary> /// Specialized wireframe graphics factory which converts path data to 2D polylines. /// </summary> /// <remarks> /// Texts, points, rays, xlines and images are ignored. /// </remarks> public class PolygonWireframeGraphicsFactory : IWireframeGraphicsFactory { private readonly List<Polyline2D> collectedPolylines = new List<Polyline2D>(); /// <summary> /// Convert the relevant part of a model to polylines. /// </summary> /// <reamrks> /// The polylines are sorted in drawing order. /// </reamrks> /// <param name="model">The model.</param> /// <param name="graphicsConfig">Graphics configuration, useful for tuning accuracy</param> /// <returns>List of polylines.</returns> public static List<Polyline2D> ConvertModelToPolylines(DxfModel model, GraphicsConfig graphicsConfig) { DrawContext.Wireframe wireframe = new DrawContext.Wireframe.ModelSpace(model, graphicsConfig, Matrix4D.Identity); PolygonWireframeGraphicsFactory factory = new PolygonWireframeGraphicsFactory(); model.Draw(wireframe, factory); return factory.collectedPolylines; } #region IWireframeGraphicsFactory Implementation public void BeginEntity(DxfEntity entity, DrawContext.Wireframe drawContext) { // ignored } public void EndEntity() { // ignored } public void BeginInsert(DxfInsert insert) { // ignore } public void EndInsert() { // ignore } public void CreateDot(DxfEntity entity, DrawContext.Wireframe drawContext, ArgbColor color, bool forText, Vector4D position) { // ignore point } public void CreateLine(DxfEntity entity, DrawContext.Wireframe drawContext, ArgbColor color, bool forText, Vector4D start, Vector4D end) { collectedPolylines.Add(new Polyline2D(start.ToPoint2D(), end.ToPoint2D())); } public void CreateRay(DxfEntity entity, DrawContext.Wireframe drawContext, ArgbColor color, Segment4D segment) { // ignore ray } public void CreateXLine(DxfEntity entity, DrawContext.Wireframe drawContext, ArgbColor color, Vector4D? startPoint, Segment4D segment) { // ignore xline } public void CreatePath(DxfEntity entity, DrawContext.Wireframe drawContext, ArgbColor color, bool forText, IList<Polyline4D> polylines, bool fill, bool correctForBackgroundColor) { if (forText) { // should not happen, see SupportsText below return; } // maybe you want to ignore filled paths, too foreach (Polyline4D poly4d in polylines) { Polyline2D poly2d = new Polyline2D(poly4d.Count, poly4d.Closed); foreach (Vector4D v4d in poly4d) { poly2d.Add(v4d.ToPoint2D()); } collectedPolylines.Add(poly2d); } } public void CreatePathAsOne(DxfEntity entity, DrawContext.Wireframe drawContext, ArgbColor color, bool forText, IList<Polyline4D> polylines, bool fill, bool correctForBackgroundColor) { // maybe you want to ignore these, too CreatePath(entity, drawContext, color, forText, polylines, fill, correctForBackgroundColor); } public void CreateShape(DxfEntity entity, DrawContext.Wireframe drawContext, ArgbColor color, bool forText, IShape4D shape) { CreatePathAsOne(entity, drawContext, color, forText, shape.ToPolylines4D(), shape.IsFilled, false); } public bool SupportsText { get { return true; } // by returning true here only the text specific methods below will be use } public void CreateText(DxfText text, DrawContext.Wireframe drawContext, ArgbColor color) { // ignore text } public void CreateMText(DxfMText text, DrawContext.Wireframe drawContext) { // ignore text } public void CreateImage(DxfRasterImage rasterImage, DrawContext.Wireframe drawContext, Polyline4D clipPolygon, Polyline4D imageBoundary, Vector4D transformedOrigin, Vector4D transformedXAxis, Vector4D transformedYAxis) { // ignore images } public void CreateScalableImage(DxfEntity entity, DrawContext.Wireframe drawContext, IBitmapProvider bitmapProvider, Size2D displaySize, Vector4D transformedOrigin, Vector4D transformedXAxis, Vector4D transformedYAxis) { throw new NotImplementedException(); } #endregion }
The number of polylines collect from your file is 226. - Wout
Ravi Magod
9/16/2015 2:24 PM
Hi Thanks. I was able to get the same result. Where does one find the property Start, End in ww.math.geometry.Polyline2D. I can see getReverse and getLength. I also observe that each Polyline2D contains a list of Point2D in each item. Is the first one Start and Last one End? How does one convert this into a DxfPolyline which requires a series of vertex and bulge? Regards Ravi Magod
Wout
9/16/2015 2:30 PM
Please create a new topic if you have a question that is unrelated to the existing topic. - Wout
1