瀏覽代碼

Gerber support for single quadrant arcs (G74).

Juan Pablo Caram 11 年之前
父節點
當前提交
45327552de
共有 7 個文件被更改,包括 126 次插入9 次删除
  1. 二進制
      bugs/.doctrees/index.doctree
  2. 1 1
      bugs/_sources/index.txt
  3. 10 0
      bugs/active.html
  4. 35 0
      bugs/excellonparse.rst
  5. 4 0
      bugs/index.html
  6. 1 1
      bugs/index.rst
  7. 75 7
      camlib.py

二進制
bugs/.doctrees/index.doctree


+ 1 - 1
bugs/_sources/index.txt

@@ -12,7 +12,7 @@ Contents:
    :maxdepth: 2
 
    active
-
+   excellonparse
 
 Indices and tables
 ==================

+ 10 - 0
bugs/active.html

@@ -24,6 +24,7 @@
     <script type="text/javascript" src="_static/underscore.js"></script>
     <script type="text/javascript" src="_static/doctools.js"></script>
     <link rel="top" title="FlatCAM Bugs 1 documentation" href="index.html" />
+    <link rel="next" title="Excellon Parser" href="excellonparse.html" />
     <link rel="prev" title="Welcome to FlatCAM Bugs’s documentation!" href="index.html" /> 
   </head>
   <body>
@@ -33,6 +34,9 @@
         <li class="right" style="margin-right: 10px">
           <a href="genindex.html" title="General Index"
              accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="excellonparse.html" title="Excellon Parser"
+             accesskey="N">next</a> |</li>
         <li class="right" >
           <a href="index.html" title="Welcome to FlatCAM Bugs’s documentation!"
              accesskey="P">previous</a> |</li>
@@ -131,6 +135,9 @@ zeros.</p>
   <h4>Previous topic</h4>
   <p class="topless"><a href="index.html"
                         title="previous chapter">Welcome to FlatCAM Bugs&#8217;s documentation!</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="excellonparse.html"
+                        title="next chapter">Excellon Parser</a></p>
   <h3>This Page</h3>
   <ul class="this-page-menu">
     <li><a href="_sources/active.txt"
@@ -159,6 +166,9 @@ zeros.</p>
         <li class="right" style="margin-right: 10px">
           <a href="genindex.html" title="General Index"
              >index</a></li>
+        <li class="right" >
+          <a href="excellonparse.html" title="Excellon Parser"
+             >next</a> |</li>
         <li class="right" >
           <a href="index.html" title="Welcome to FlatCAM Bugs’s documentation!"
              >previous</a> |</li>

+ 35 - 0
bugs/excellonparse.rst

@@ -0,0 +1,35 @@
+Excellon Parser
+===============
+
+List of test files and their settings
+-------------------------------------
+
+========================== ============== ========= ===================
+File                       Settings       Parsed Ok Example
+========================== ============== ========= ===================
+FlatCAM_Drilling_Test.drl  METRIC         YES       X76324 -> 76mm
+Drill_All.drl              METRIC         NO        X019708 -> 1.97mm X
+TFTadapter.drl             METRIC,TZ      YES?      X4.572 -> 4.57mm
+rfduino dip.drl_           METRIC,TZ      NO        X236220 -> 23mm X
+X-Y CONTROLLER - Drill...  METRIC         YES       X76213 -> 76mm
+ucontrllerBoard.drl        INCH,TZ        YES       X1.96572
+holes.drl                  INCH           YES       Y+019500 -> 1.95in
+BLDC2003Through.drl        INCH           YES       X+023625 -> 2.3in
+PlacaReles.drl             INCH,TZ        YES       Y-8200 -> -0.82in
+AVR_Transistor_Tester.DRL  INCH           YES       X033000 -> 3.3in
+DRL                        INCH,00.0000   YES/NO*   X004759 -> 0.47in
+========================== ============== ========= ===================
+
+(*) The units format is not recognized, thus it is parsed correctly
+as long as the project is set for inches already.
+
+Parser was:
+
+.. code-block:: python
+
+   def parse_number(self, number_str):
+     if self.zeros == "L":
+       match = self.leadingzeros_re.search(number_str)
+       return float(number_str)/(10**(len(match.group(1)) + len(match.group(2)) - 2))
+     else:  # Trailing
+       return float(number_str)/10000

+ 4 - 0
bugs/index.html

@@ -54,6 +54,10 @@
 <li class="toctree-l2"><a class="reference internal" href="active.html#drill-number-parsing">Drill number parsing</a></li>
 </ul>
 </li>
+<li class="toctree-l1"><a class="reference internal" href="excellonparse.html">Excellon Parser</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="excellonparse.html#list-of-test-files-and-their-settings">List of test files and their settings</a></li>
+</ul>
+</li>
 </ul>
 </div>
 </div>

+ 1 - 1
bugs/index.rst

@@ -12,7 +12,7 @@ Contents:
    :maxdepth: 2
 
    active
-
+   excellonparse
 
 Indices and tables
 ==================

+ 75 - 7
camlib.py

@@ -200,7 +200,7 @@ class Geometry(object):
             log.warning("Solid_geometry not computed yet.")
             return 0
         bounds = self.bounds()
-        return (bounds[2]-bounds[0], bounds[3]-bounds[1])
+        return bounds[2]-bounds[0], bounds[3]-bounds[1]
         
     def get_empty_area(self, boundary=None):
         """
@@ -1164,6 +1164,7 @@ class Gerber (Geometry):
                 # 2-clockwise, 3-counterclockwise
                 match = self.circ_re.search(gline)
                 if match:
+                    arcdir = [None, None, "cw", "ccw"]
 
                     mode, x, y, i, j, d = match.groups()
                     try:
@@ -1224,9 +1225,8 @@ class Gerber (Geometry):
                     if quadrant_mode == 'MULTI':
                         center = [i + current_x, j + current_y]
                         radius = sqrt(i**2 + j**2)
-                        start = arctan2(-j, -i)
-                        stop = arctan2(-center[1] + y, -center[0] + x)
-                        arcdir = [None, None, "cw", "ccw"]
+                        start = arctan2(-j, -i)  # Start angle
+                        stop = arctan2(-center[1] + y, -center[0] + x)  # Stop angle
                         this_arc = arc(center, radius, start, stop,
                                        arcdir[current_interpolation_mode],
                                        self.steps_per_circ)
@@ -1243,7 +1243,56 @@ class Gerber (Geometry):
                         continue
 
                     if quadrant_mode == 'SINGLE':
-                        log.warning("Single quadrant arc are not implemented yet. (%d)" % line_num)
+                        #log.warning("Single quadrant arc are not implemented yet. (%d)" % line_num)
+
+                        center_candidates = [
+                            [i + current_x, j + current_y],
+                            [-i + current_x, j + current_y],
+                            [i + current_x, -j + current_y],
+                            [-i + current_x, -j + current_y]
+                        ]
+
+                        valid = False
+                        log.debug("I: %f  J: %f" % (i, j))
+                        for center in center_candidates:
+                            radius = sqrt(i**2 + j**2)
+
+                            # Make sure radius to start is the same as radius to end.
+                            radius2 = sqrt((center[0] - x)**2 + (center[1] - y)**2)
+                            if radius2 < radius*0.95 or radius2 > radius*1.05:
+                                continue  # Not a valid center.
+
+                            # Correct i and j and continue as with multi-quadrant.
+                            i = center[0] - current_x
+                            j = center[1] - current_y
+
+                            start = arctan2(-j, -i)  # Start angle
+                            stop = arctan2(-center[1] + y, -center[0] + x)  # Stop angle
+                            angle = abs(arc_angle(start, stop, arcdir[current_interpolation_mode]))
+                            log.debug("ARC START: %f, %f  CENTER: %f, %f  STOP: %f, %f" %
+                                      (current_x, current_y, center[0], center[1], x, y))
+                            log.debug("START Ang: %f, STOP Ang: %f, DIR: %s, ABS: %.12f <= %.12f: %s" %
+                                      (start*180/pi, stop*180/pi, arcdir[current_interpolation_mode],
+                                       angle*180/pi, pi/2*180/pi, angle <= (pi+1e-6)/2))
+
+                            if angle <= (pi+1e-6)/2:
+                                log.debug("########## ACCEPTING ARC ############")
+                                this_arc = arc(center, radius, start, stop,
+                                               arcdir[current_interpolation_mode],
+                                               self.steps_per_circ)
+                                current_x = this_arc[-1][0]
+                                current_y = this_arc[-1][1]
+                                path += this_arc
+                                last_path_aperture = current_aperture
+                                valid = True
+                                break
+
+                        if valid:
+                            continue
+                        else:
+                            log.warning("Invalid arc in line %d." % line_num)
+
+
 
                 ### Operation code alone
                 # Operation code alone, usually just D03 (Flash)
@@ -1786,15 +1835,24 @@ class Excellon(Geometry):
         :rtype: foat
         """
         if self.zeros == "L":
+            # With leading zeros, when you type in a coordinate,
+            # the leading zeros must always be included.  Trailing zeros
+            # are unneeded and may be left off. The CNC-7 will automatically add them.
             # r'^[-\+]?(0*)(\d*)'
             # 6 digits are divided by 10^4
             # If less than size digits, they are automatically added,
-            # 5 digits then are divided by 10^3
+            # 5 digits then are divided by 10^3 and so on.
             match = self.leadingzeros_re.search(number_str)
             return float(number_str)/(10**(len(match.group(1)) + len(match.group(2)) - 2))
 
         else:  # Trailing
-            return float(number_str)/10000
+            # You must show all zeros to the right of the number and can omit
+            # all zeros to the left of the number. The CNC-7 will count the number
+            # of digits you typed and automatically fill in the missing zeros.
+            if self.units.lower() == "in":  # Inches is 00.0000
+                return float(number_str)/10000
+
+            return float(number_str)/1000  # Metric is 000.000
 
     def create_geometry(self):
         """
@@ -2621,6 +2679,16 @@ def arc(center, radius, start, stop, direction, steps_per_circ):
     return points
 
 
+def arc_angle(start, stop, direction):
+    if direction == "ccw" and stop <= start:
+        stop += 2*pi
+    if direction == "cw" and stop >= start:
+        stop -= 2*pi
+
+    angle = abs(stop - start)
+    return angle
+
+
 def clear_poly(poly, tooldia, overlap=0.1):
     """
     Creates a list of Shapely geometry objects covering the inside