implement joining and improving paths
Stefan Schuermans

Stefan Schuermans commited on 2013-01-26 23:15:34
Showing 9 changed files, with 192 additions and 3 deletions.

... ...
@@ -86,6 +86,9 @@ bool CmdParser::procCmd_read_dxf(std::istream &strm)
86 86
     return false;
87 87
   }
88 88
 
89
+  // improve paths in layers
90
+  mDrawing.improvePaths(mSettings.precision);
91
+
89 92
   return true;
90 93
 }
91 94
 
... ...
@@ -62,3 +62,14 @@ bool Drawing::loadDxf(const std::string &strFileName)
62 62
   return addDxf(strFileName);
63 63
 }
64 64
 
65
+/**
66
+ * @brief improve paths in layers
67
+ * @param[in] eqDist maximum distance of tho points to be considered equal
68
+ */
69
+void Drawing::improvePaths(double eqDist)
70
+{
71
+  Layers::iterator layer;
72
+  for (layer = mLayers.begin(); layer != mLayers.end(); ++layer)
73
+    layer->second.improvePaths(eqDist);
74
+}
75
+
... ...
@@ -36,6 +36,12 @@ public:
36 36
    */
37 37
   bool loadDxf(const std::string &strFileName);
38 38
 
39
+  /**
40
+   * @brief improve paths in layers
41
+   * @param[in] eqDist maximum distance of tho points to be considered equal
42
+   */
43
+  void improvePaths(double eqDist);
44
+
39 45
   Layers mLayers; ///< layers in drawing
40 46
 };
41 47
 
... ...
@@ -3,7 +3,7 @@
3 3
  * Copyleft: CC-BY-SA http://creativecommons.org/licenses/by-sa/3.0/
4 4
  */
5 5
 
6
-#include <vector>
6
+#include <list>
7 7
 
8 8
 #include "gcode.h"
9 9
 #include "layer.h"
... ...
@@ -20,6 +20,65 @@ Path & Layer::addPath()
20 20
   return mPaths.back();
21 21
 }
22 22
 
23
+/**
24
+ * @brief improve paths
25
+ * @param[in] eqDist maximum distance of two points to be considered equal
26
+ */
27
+void Layer::improvePaths(double eqDist)
28
+{
29
+  Paths::iterator path, other;
30
+  bool change;
31
+
32
+  // join paths with equal begin/end points
33
+  do {
34
+    change = false;
35
+    for (path = mPaths.begin(); path != mPaths.end(); ++path) {
36
+      other = path;
37
+      ++other;
38
+      while (other != mPaths.end()) {
39
+        if (other->mPoints.front().equals(path->mPoints.back(),
40
+                                          eqDist)) {
41
+          path->appendPath(*other);
42
+          other = mPaths.erase(other);
43
+          change = true;
44
+        }
45
+        else if (other->mPoints.back().equals(path->mPoints.back(),
46
+                                              eqDist)) {
47
+          path->appendReversedPath(*other);
48
+          other = mPaths.erase(other);
49
+          change = true;
50
+        }
51
+        else if (other->mPoints.back().equals(path->mPoints.front(),
52
+                                              eqDist)) {
53
+          path->prependPath(*other);
54
+          other = mPaths.erase(other);
55
+          change = true;
56
+        }
57
+        else if (other->mPoints.front().equals(path->mPoints.front(),
58
+                                               eqDist)) {
59
+          path->prependReversedPath(*other);
60
+          other = mPaths.erase(other);
61
+          change = true;
62
+        }
63
+        else
64
+          ++other;
65
+      }
66
+    }
67
+  } while (change);
68
+
69
+  // remove nearby points in paths
70
+  for (path = mPaths.begin(); path != mPaths.end(); ++path)
71
+    path->removeEqPoints(eqDist);
72
+
73
+  // remove empty paths
74
+  path = mPaths.begin();
75
+  while (path != mPaths.end())
76
+    if (path->mPoints.empty())
77
+      path = mPaths.erase(path);
78
+    else
79
+      ++path;
80
+}
81
+
23 82
 /**
24 83
  * @brief convert layer to G-code
25 84
  * @param[in] settings G-code creation settings
... ...
@@ -6,7 +6,7 @@
6 6
 #ifndef LAYER_H
7 7
 #define LAYER_H
8 8
 
9
-#include <vector>
9
+#include <list>
10 10
 
11 11
 #include "gcode.h"
12 12
 #include "path.h"
... ...
@@ -15,7 +15,7 @@
15 15
 /// layer of drawing
16 16
 class Layer {
17 17
 public:
18
-  typedef std::vector<Path> Paths; ///< type for paths in layer
18
+  typedef std::list<Path> Paths; ///< type for paths in layer
19 19
 
20 20
   /**
21 21
    * @brief add a new empty path to the layer
... ...
@@ -23,6 +23,12 @@ public:
23 23
    */
24 24
   Path & addPath();
25 25
 
26
+  /**
27
+   * @brief improve paths
28
+   * @param[in] eqDist maximum distance of two points to be considered equal
29
+   */
30
+  void improvePaths(double eqDist);
31
+
26 32
   /**
27 33
    * @brief convert layer to G-code
28 34
    * @param[in] settings G-code creation settings
... ...
@@ -29,6 +29,62 @@ void Path::addPoint(double x, double y)
29 29
   addPoint(Point(x, y));
30 30
 }
31 31
 
32
+/**
33
+ * @brief prepend other path to this one
34
+ * @param[in] other other path to prepend
35
+ */
36
+void Path::prependPath(const Path &other)
37
+{
38
+  mPoints.insert(mPoints.begin(),
39
+                 other.mPoints.begin(), other.mPoints.end());
40
+}
41
+
42
+/**
43
+ * @brief prepend other path in reverse to this one
44
+ * @param[in] other other path to prepend
45
+ */
46
+void Path::prependReversedPath(const Path &other)
47
+{
48
+  mPoints.insert(mPoints.begin(),
49
+                 other.mPoints.rbegin(), other.mPoints.rend());
50
+}
51
+
52
+/**
53
+ * @brief append other path to this one
54
+ * @param[in] other other path to appepend
55
+ */
56
+void Path::appendPath(const Path &other)
57
+{
58
+  mPoints.insert(mPoints.end(),
59
+                 other.mPoints.begin(), other.mPoints.end());
60
+}
61
+
62
+/**
63
+ * @brief append other path in reverse to this one
64
+ * @param[in] other other path to appepend
65
+ */
66
+void Path::appendReversedPath(const Path &other)
67
+{
68
+  mPoints.insert(mPoints.end(),
69
+                 other.mPoints.rbegin(), other.mPoints.rend());
70
+}
71
+
72
+/**
73
+ * @brief remove points too close to each other
74
+ * @param[in] eqDist maximum distance of two points to be considered equal
75
+ */
76
+void Path::removeEqPoints(double eqDist)
77
+{
78
+  Points::iterator pt = mPoints.begin();
79
+  while (pt != mPoints.end()) {
80
+    Points::iterator next = pt + 1;
81
+    if (next != mPoints.end() && pt->equals(*next, eqDist))
82
+      mPoints.erase(next);
83
+    else
84
+      pt++;
85
+  }
86
+}
87
+
32 88
 /**
33 89
  * @brief convert path to G-code
34 90
  * @param[in] settings G-code creation settings
... ...
@@ -30,6 +30,36 @@ public:
30 30
    */
31 31
   void addPoint(double x, double y);
32 32
 
33
+  /**
34
+   * @brief prepend other path to this one
35
+   * @param[in] other other path to prepend
36
+   */
37
+  void prependPath(const Path &other);
38
+
39
+  /**
40
+   * @brief prepend other path in reverse to this one
41
+   * @param[in] other other path to prepend
42
+   */
43
+  void prependReversedPath(const Path &other);
44
+
45
+  /**
46
+   * @brief append other path to this one
47
+   * @param[in] other other path to appepend
48
+   */
49
+  void appendPath(const Path &other);
50
+
51
+  /**
52
+   * @brief append other path in reverse to this one
53
+   * @param[in] other other path to appepend
54
+   */
55
+  void appendReversedPath(const Path &other);
56
+
57
+  /**
58
+   * @brief remove points too close to each other
59
+   * @param[in] eqDist maximum distance of two points to be considered equal
60
+   */
61
+  void removeEqPoints(double eqDist);
62
+
33 63
   /**
34 64
    * @brief convert path to G-code
35 65
    * @param[in] settings G-code creation settings
... ...
@@ -82,3 +82,13 @@ Point &Point::operator/=(double factor)
82 82
   return *this;
83 83
 }
84 84
 
85
+/**
86
+ * @brief check if point is equal to another one
87
+ * @param[in] that other point
88
+ * @param[in] eqDist maximum distance of two points to be considered equal
89
+ */
90
+bool Point::equals(const Point &that, double eqDist) const
91
+{
92
+  return (*this - that).abs_sq() <= eqDist * eqDist;
93
+}
94
+
... ...
@@ -22,6 +22,14 @@ public:
22 22
   Point &operator-=(const Point &that);
23 23
   Point &operator*=(double factor);
24 24
   Point &operator/=(double factor);
25
+
26
+  /**
27
+   * @brief check if point is equal to another one
28
+   * @param[in] that other point
29
+   * @param[in] eqDist maximum distance of two points to be considered equal
30
+   */
31
+  bool equals(const Point &that, double eqDist) const;
32
+
25 33
   double mX; ///< x coordinate
26 34
   double mY; ///< y coordinate
27 35
 };
28 36