コード例 #1
0
ファイル: Settings.py プロジェクト: signotheque/pycam
 def parse(self, text):
     text_stream = StringIO.StringIO(text)
     config = ConfigParser.SafeConfigParser()
     config.readfp(text_stream)
     for config_dict, section in ((self.bounds, "Bounds"),
             (self.tool_settings, "Tool"),
             (self.process_settings, "Process")):
         for key, value_type in self.SECTIONS[section].items():
             value_raw = config.get(section, key, None)
             if value_raw is None:
                 continue
             elif value_type == bool:
                 value = value_raw.lower() in ("1", "true", "yes", "on")
             elif isinstance(value_type, basestring) \
                     and (value_type.startswith("list_of_")):
                 item_type = value_type[len("list_of_"):]
                 if item_type == "float":
                     item_type = float
                 else:
                     continue
                 try:
                     value = [item_type(one_val)
                             for one_val in value_raw.split(",")]
                 except ValueError:
                     log.warn("Settings: Ignored invalid setting due to " \
                             + "a failed list type parsing: " \
                             + "(%s -> %s): %s" % (section, key, value_raw))
             else:
                 try:
                     value = value_type(value_raw)
                 except ValueError:
                     log.warn("Settings: Ignored invalid setting " \
                             + "(%s -> %s): %s" % (section, key, value_raw))
             config_dict[key] = value
コード例 #2
0
ファイル: DXFImporter.py プロジェクト: stevegt/pycam
 def parse_arc(self, circle=False):
     start_line = self.line_number
     # the z-level defaults to zero (for 2D models)
     center = [None, None, 0]
     color = None
     radius = None
     if circle:
         angle_start = 0
         angle_end = 360
     else:
         angle_start = None
         angle_end = None
     key, value = self._read_key_value()
     while (not key is None) and (key != self.KEYS["MARKER"]):
         if key == self.KEYS["P1_X"]:
             center[0] = value
         elif key == self.KEYS["P1_Y"]:
             center[1] = value
         elif key == self.KEYS["P1_Z"]:
             center[2] = value
         elif key == self.KEYS["RADIUS"]:
             radius = value
         elif key == self.KEYS["ANGLE_START"]:
             angle_start = value
         elif key == self.KEYS["ANGLE_END"]:
             angle_end = value
         elif key == self.KEYS["COLOR"]:
             color = value
         else:
             pass
         key, value = self._read_key_value()
     end_line = self.line_number
     # The last lines were not used - they are just the marker for the next
     # item.
     if not key is None:
         self._push_on_stack(key, value)
     if (None in center) or (None in (radius, angle_start, angle_end)):
         log.warn("DXFImporter: Incomplete ARC definition between line " \
                 + "%d and %d" % (start_line, end_line))
     else:
         if self._color_as_height and (not color is None):
             # use the color code as the z coordinate
             center[2] = float(color) / 255
         center = tuple(center)
         xy_point_coords = pycam.Geometry.get_points_of_arc(center, radius, angle_start, angle_end)
         # Somehow the order of points seems to be the opposite of what is
         # expected.
         xy_point_coords.reverse()
         if len(xy_point_coords) > 1:
             for index in range(len(xy_point_coords) - 1):
                 p1 = xy_point_coords[index]
                 p1 = (p1[0], p1[1], center[2])
                 p2 = xy_point_coords[index + 1]
                 p2 = (p2[0], p2[1], center[2])
                 if p1 != p2:
                     self.lines.append(Line(p1, p2))
         else:
             log.warn("DXFImporter: Ignoring tiny ARC (between input " + \
                     "line %d and %d): %s / %s (%s - %s)" % (start_line,
                     end_line, center, radius, angle_start, angle_end))
コード例 #3
0
 def parse_vertex(self):
     start_line = self.line_number
     point = [None, None, 0]
     color = None
     bulge = None
     key, value = self._read_key_value()
     while (key is not None) and (key != self.KEYS["MARKER"]):
         if key == self.KEYS["P1_X"]:
             point[0] = value
         elif key == self.KEYS["P1_Y"]:
             point[1] = value
         elif key == self.KEYS["P1_Z"]:
             point[2] = value
         elif key == self.KEYS["COLOR"]:
             color = value
         elif key == self.KEYS["VERTEX_BULGE"]:
             bulge = value
         else:
             pass
         key, value = self._read_key_value()
     end_line = self.line_number
     if key is not None:
         self._push_on_stack(key, value)
     if self._color_as_height and (color is not None):
         # use the color code as the z coordinate
         point[2] = float(color) / 255
     if None in point:
         log.warn(
             "DXFImporter: Missing attribute of VERTEX item between line %d and %d",
             start_line, end_line)
     else:
         self._open_sequence_items.append(
             ((point[0], point[1], point[2]), bulge))
コード例 #4
0
ファイル: DXFImporter.py プロジェクト: I--Fox--I/pycam
 def parse_vertex(self):
     start_line = self.line_number
     point = [None, None, 0]
     color = None
     bulge = None
     key, value = self._read_key_value()
     while (not key is None) and (key != self.KEYS["MARKER"]):
         if key == self.KEYS["P1_X"]:
             point[0] = value
         elif key == self.KEYS["P1_Y"]:
             point[1] = value
         elif key == self.KEYS["P1_Z"]:
             point[2] = value
         elif key == self.KEYS["COLOR"]:
             color = value
         elif key == self.KEYS["VERTEX_BULGE"]:
             bulge = value
         else:
             pass
         key, value = self._read_key_value()
     end_line = self.line_number
     if not key is None:
         self._push_on_stack(key, value)
     if self._color_as_height and (not color is None):
         # use the color code as the z coordinate
         point[2] = float(color) / 255
     if None in point:
         log.warn("DXFImporter: Missing attribute of VERTEX item" + \
                 "between line %d and %d" % (start_line, end_line))
     else:
         self._open_sequence_items.append(
                 (Point(point[0], point[1], point[2]), bulge))
コード例 #5
0
 def _carefully_decode(self, text):
     try:
         return text.decode("utf-8")
     except UnicodeDecodeError:
         log.warn("DXFImporter: Invalid character in string in line %d",
                  self.line_number)
         return text.decode("utf-8", errors="ignore")
コード例 #6
0
ファイル: DXFImporter.py プロジェクト: I--Fox--I/pycam
 def close_sequence(self):
     start_line = self.line_number
     if self._open_sequence == "POLYLINE":
         self.parse_polyline(False)
     else:
         log.warn("DXFImporter: unexpected SEQEND found at line %d" % \
                 start_line)
コード例 #7
0
ファイル: Model.py プロジェクト: chriskyfung/MakerDroid
 def combine_triangles(t1, t2):
     unique_vertices = []
     shared_vertices = []
     for point in t1.get_points():
         for point2 in t2.get_points():
             if point == point2:
                 shared_vertices.append(point)
                 break
         else:
             unique_vertices.append(point)
     if len(shared_vertices) != 2:
         return None
     for point in t2.get_points():
         for point2 in shared_vertices:
             if point == point2:
                 break
         else:
             unique_vertices.append(point)
     if len(unique_vertices) != 2:
         log.error("Invalid number of vertices: %s" % unique_vertices)
         return None
     if abs(unique_vertices[0].sub(unique_vertices[1]).norm - \
             shared_vertices[0].sub(shared_vertices[1]).norm) < epsilon:
         try:
             return Rectangle(unique_vertices[0], unique_vertices[1],
                     shared_vertices[0], shared_vertices[1],
                     normal=t1.normal)
         except ValueError:
             log.warn("Triangles not combined: %s, %s" % (unique_vertices,
                     shared_vertices))
             return None
     else:
         return None
コード例 #8
0
ファイル: Project.py プロジェクト: I--Fox--I/pycam
 def load_preferences(self):
     """ load all settings that are available in the Preferences window from
     a file in the user's home directory """
     config_filename = pycam.Gui.Settings.get_config_filename()
     if config_filename is None:
         # failed to create the personal preferences directory
         return
     config = ConfigParser.ConfigParser()
     if not config.read(config_filename):
         # no config file was read
         return
     # report any ignored (obsolete) preference keys present in the file
     for item, value in config.items("DEFAULT"):
         if not item in PREFERENCES_DEFAULTS.keys():
             log.warn("Skipping obsolete preference item: %s" % str(item))
     for item in PREFERENCES_DEFAULTS.keys():
         if not config.has_option("DEFAULT", item):
             # a new preference setting is missing in the (old) file
             continue
         value_raw = config.get("DEFAULT", item)
         old_value = self.settings.get(item)
         value_type = type(PREFERENCES_DEFAULTS[item])
         if isinstance(value_type(), basestring):
             # keep strings as they are
             value = str(value_raw)
         else:
             # parse tuples, integers, bools, ...
             value = eval(value_raw)
         self.settings.set(item, value)
コード例 #9
0
ファイル: __init__.py プロジェクト: zancas/pycam
 def load_preferences(self):
     """ load all settings that are available in the Preferences window from
     a file in the user's home directory """
     config_filename = pycam.Gui.Settings.get_config_filename()
     if config_filename is None:
         # failed to create the personal preferences directory
         return
     config = ConfigParser()
     if not config.read(config_filename):
         # no config file was read
         return
     # report any ignored (obsolete) preference keys present in the file
     for item, value in config.items("DEFAULT"):
         if item not in PREFERENCES_DEFAULTS.keys():
             log.warn("Skipping obsolete preference item: %s", str(item))
     for item in PREFERENCES_DEFAULTS:
         if not config.has_option("DEFAULT", item):
             # a new preference setting is missing in the (old) file
             continue
         value_raw = config.get("DEFAULT", item)
         value_type = type(PREFERENCES_DEFAULTS[item])
         if hasattr(value_type(), "split"):
             # keep strings as they are
             value = str(value_raw)
         else:
             # parse tuples, integers, bools, ...
             value = eval(value_raw)
         self.settings.set(item, value)
コード例 #10
0
 def __init__(self, title, message):
     try:
         import Tkinter
     except ImportError:
         # tk is not installed
         log.warn("Failed to show error dialog due to a missing Tkinter Python package.")
         return
     try:
         root = Tkinter.Tk()
     except Tkinter.TclError as err_msg:
         log.info("Failed to create error dialog window (%s). Probably you are running PyCAM "
                  "from a terminal.", err_msg)
         return
     root.title(title)
     root.bind("<Return>", self.finish)
     root.bind("<Escape>", self.finish)
     root.minsize(300, 100)
     self.root = root
     frame = Tkinter.Frame(root)
     frame.pack()
     # add text output as label
     message = Tkinter.Message(root, text=message)
     # we need some space for the dependency report
     message["width"] = 800
     message.pack()
     # add the "close" button
     close = Tkinter.Button(root, text="Close")
     close["command"] = self.finish
     close.pack(side=Tkinter.BOTTOM)
     root.mainloop()
コード例 #11
0
def parse_toolpath_settings(filename):
    """ parse potential PyCAM settings from a given file

    This is mainly useful to retrieve task settings from a GCode file.
    @value filename: the name of the file to be read
    @type filename: str
    @returns: a dictionary (of all setting names and values) and the content
            of the 'comment' section (as a single string)
    @rtype: tuple(dict, str)
    """
    keywords = {}
    in_meta_zone = False
    meta_content = []
    if filename == "-":
        # read from stdin, if the input filename is "-"
        infile = sys.stdin
        close_file = False
    else:
        # open the file
        try:
            infile = pycam.Utils.URIHandler(filename).open()
        except IOError, err_msg:
            log.warn("ToolpathSettingsParser: Failed to read file (%s): %s" % \
                    (filename, err_msg))
            return None
        close_file = True
コード例 #12
0
ファイル: DXFImporter.py プロジェクト: chriskyfung/MakerDroid
 def parse_lwpolyline(self):
     start_line = self.line_number
     points = []
     def add_point(p_array):
         # fill all "None" values with zero
         for index in range(len(p_array)):
             if p_array[index] is None:
                 if (index == 0) or (index == 1):
                     log.debug("DXFImporter: weird LWPOLYLINE input " + \
                             "date in line %d: %s" % \
                             (self.line_number, p_array))
                 p_array[index] = 0
         points.append(Point(p_array[0], p_array[1], p_array[2]))
     current_point = [None, None, None]
     key, value = self._read_key_value()
     while (not key is None) and (key != self.KEYS["MARKER"]):
         if key == self.KEYS["P1_X"]:
             axis = 0
         elif key == self.KEYS["P1_Y"]:
             axis = 1
         elif not self._color_as_height and (key == self.KEYS["P1_Z"]):
             axis = 2
         elif self._color_as_height and (key == self.KEYS["COLOR"]):
             # interpret the color as the height
             axis = 2
             value = float(value) / 255
         else:
             axis = None
         if not axis is None:
             if current_point[axis] is None:
                 # The current point definition is not complete, yet.
                 current_point[axis] = value
             else:
                 # The current point seems to be complete.
                 add_point(current_point)
                 current_point = [None, None, None]
                 current_point[axis] = value
         key, value = self._read_key_value()
     end_line = self.line_number
     # The last lines were not used - they are just the marker for the next
     # item.
     if not key is None:
         self._push_on_stack(key, value)
     # check if there is a remaining item in "current_point"
     if len(current_point) != current_point.count(None):
         add_point(current_point)
     if len(points) < 2:
         # too few points for a polyline
         log.warn("DXFImporter: Empty LWPOLYLINE definition between line " \
                 + "%d and %d" % (start_line, end_line))
     else:
         for index in range(len(points) - 1):
             point = points[index]
             next_point = points[index + 1]
             if point != next_point:
                 self.lines.append(Line(point, next_point))
             else:
                 log.warn("DXFImporter: Ignoring zero-length LINE " \
                         + "(between input line %d and %d): %s" \
                         % (start_line, end_line, point))
コード例 #13
0
ファイル: Model.py プロジェクト: weeberp/MakerDroid
 def combine_triangles(t1, t2):
     unique_vertices = []
     shared_vertices = []
     for point in t1.get_points():
         for point2 in t2.get_points():
             if point == point2:
                 shared_vertices.append(point)
                 break
         else:
             unique_vertices.append(point)
     if len(shared_vertices) != 2:
         return None
     for point in t2.get_points():
         for point2 in shared_vertices:
             if point == point2:
                 break
         else:
             unique_vertices.append(point)
     if len(unique_vertices) != 2:
         log.error("Invalid number of vertices: %s" % unique_vertices)
         return None
     if abs(unique_vertices[0].sub(unique_vertices[1]).norm - \
             shared_vertices[0].sub(shared_vertices[1]).norm) < epsilon:
         try:
             return Rectangle(unique_vertices[0],
                              unique_vertices[1],
                              shared_vertices[0],
                              shared_vertices[1],
                              normal=t1.normal)
         except ValueError:
             log.warn("Triangles not combined: %s, %s" %
                      (unique_vertices, shared_vertices))
             return None
     else:
         return None
コード例 #14
0
def parse_toolpath_settings(filename):
    """ parse potential PyCAM settings from a given file

    This is mainly useful to retrieve task settings from a GCode file.
    @value filename: the name of the file to be read
    @type filename: str
    @returns: a dictionary (of all setting names and values) and the content
            of the 'comment' section (as a single string)
    @rtype: tuple(dict, str)
    """
    keywords = {}
    in_meta_zone = False
    meta_content = []
    if filename == "-":
        # read from stdin, if the input filename is "-"
        infile = sys.stdin
        close_file = False
    else:
        # open the file
        try:
            infile = pycam.Utils.URIHandler(filename).open()
        except IOError, err_msg:
            log.warn("ToolpathSettingsParser: Failed to read file (%s): %s" % \
                    (filename, err_msg))
            return None
        close_file = True
コード例 #15
0
 def close_sequence(self):
     start_line = self.line_number
     if self._open_sequence == "POLYLINE":
         self.parse_polyline(False)
     else:
         log.warn("DXFImporter: unexpected SEQEND found at line %d",
                  start_line)
コード例 #16
0
def recommends_details_gtk():
    result = {}
    try:
        import gi.repository.WebKit2  # noqa F401
        result["webkitgtk"] = True
    except ImportError as err_msg:
        log.warn("Failed to import WebKitGTK: %s", str(err_msg))
        result["webkitgtk"] = False
コード例 #17
0
ファイル: common.py プロジェクト: signotheque/pycam
def recommends_details_gtk():
    result = {}
    try:
        import gtk.gtkgl
        result["gtkgl"] = True
        result["gl"] = True
    except ImportError, err_msg:
        log.warn("Failed to import OpenGL for GTK (ImportError): %s" % \
                str(err_msg))
        result["gtkgl"] = False
コード例 #18
0
ファイル: MotionGrid.py プロジェクト: patyork/pycam
def get_lines_layer(lines, z, last_z=None, step_width=None,
        milling_style=MILLING_STYLE_CONVENTIONAL):
    get_proj_point = lambda proj_point: (proj_point[0], proj_point[1], z)
    projected_lines = []
    for line in lines:
        if (not last_z is None) and (last_z < line.minz):
            # the line was processed before
            continue
        elif line.minz < z < line.maxz:
            # Split the line at the point at z level and do the calculation
            # for both point pairs.
            factor = (z - line.p1[2]) / (line.p2[2] - line.p1[2])
            plane_point = padd(line.p1, pmul(line.vector, factor))
            if line.p1[2] < z:
                p1 = get_proj_point(line.p1)
                p2 = line.p2
            else:
                p1 = line.p1
                p2 = get_proj_point(line.p2)
            projected_lines.append(Line(p1, plane_point))
            yield Line(plane_point, p2)
        elif line.minz < last_z < line.maxz:
            plane = Plane((0, 0, last_z), (0, 0, 1, 'v'))
            cp = plane.intersect_point(line.dir, line.p1)[0]
            # we can be sure that there is an intersection
            if line.p1[2] > last_z:
                p1, p2 = cp, line.p2
            else:
                p1, p2 = line.p1, cp
            projected_lines.append(Line(p1, p2))
        else:
            if line.maxz <= z:
                # the line is completely below z
                projected_lines.append(Line(get_proj_point(line.p1),
                        get_proj_point(line.p2)))
            elif line.minz >= z:
                projected_lines.append(line)
            else:
                log.warn("Unexpected condition 'get_lines_layer': " + \
                        "%s / %s / %s / %s" % (line.p1, line.p2, z, last_z))
    # process all projected lines
    for line in projected_lines:
        points = []
        if step_width is None:
            points.append(line.p1)
            points.append(line.p2)
        else:
            if isiterable(step_width):
                steps = step_width
            else:
                steps = floatrange(0.0, line.len, inc=step_width)
            for step in steps:
                next_point = padd(line.p1, pmul(line.dir, step))
                points.append(next_point)
        yield points
コード例 #19
0
 def save_preferences(self):
     """ save all settings (see Preferences window) to a file in the user's home directory """
     config = ConfigParser()
     for item in PREFERENCES_DEFAULTS:
         config.set("DEFAULT", item, json.dumps(self.settings.get(item)))
     try:
         with pycam.Gui.Settings.open_preferences_file(
                 mode="w") as out_file:
             config.write(out_file)
     except OSError as exc:
         log.warn("Failed to write preferences file: %s", exc)
コード例 #20
0
ファイル: locations.py プロジェクト: valeriob01/pycam
def create_named_temporary_file(suffix=None):
    file_handle, filename = tempfile.mkstemp(suffix=".dxf")
    os.close(file_handle)
    try:
        yield filename
    finally:
        if os.path.isfile(filename):
            try:
                os.remove(filename)
            except OSError as exc:
                log.warn("Failed to remove temporary file (%s): %s", filename, exc)
コード例 #21
0
ファイル: pycampy.py プロジェクト: chriskyfung/MakerDroid
def get_default_model():
    """ return a filename or a Model instance """
    # try to load the default model file ("pycam" logo)
    for inputdir in EXAMPLE_MODEL_LOCATIONS:
        inputfile = os.path.join(inputdir, DEFAULT_MODEL_FILE)
        if os.path.isfile(inputfile):
            return inputfile
    else:
        # fall back to the simple test model
        log.warn("Failed to find the default model (%s) in the " \
                "following locations: %s" % (DEFAULT_MODEL_FILE,
                        ", ".join(EXAMPLE_MODEL_LOCATIONS)))
        return pycam.Importers.TestModel.get_test_model()
コード例 #22
0
ファイル: pycam.py プロジェクト: petervanderwalt/pycam-cloud
def get_default_model():
    """ return a filename or a Model instance """
    # try to load the default model file ("pycam" logo)
    for inputdir in EXAMPLE_MODEL_LOCATIONS:
        inputfile = os.path.join(inputdir, DEFAULT_MODEL_FILE)
        if os.path.isfile(inputfile):
            return inputfile
    else:
        # fall back to the simple test model
        log.warn("Failed to find the default model (%s) in the " \
                "following locations: %s" % (DEFAULT_MODEL_FILE,
                        ", ".join(EXAMPLE_MODEL_LOCATIONS)))
        return pycam.Importers.TestModel.get_test_model()
コード例 #23
0
ファイル: EngraveCutter.py プロジェクト: weeberp/MakerDroid
 def GenerateToolPathLinePush(self, pa, line, z, previous_z,
         draw_callback=None):
     if previous_z <= line.minz:
         # the line is completely above the previous level
         pass
     elif line.minz < z < line.maxz:
         # Split the line at the point at z level and do the calculation
         # for both point pairs.
         factor = (z - line.p1.z) / (line.p2.z - line.p1.z)
         plane_point = line.p1.add(line.vector.mul(factor))
         self.GenerateToolPathLinePush(pa, Line(line.p1, plane_point), z,
                 previous_z, draw_callback=draw_callback)
         self.GenerateToolPathLinePush(pa, Line(plane_point, line.p2), z,
                 previous_z, draw_callback=draw_callback)
     elif line.minz < previous_z < line.maxz:
         plane = Plane(Point(0, 0, previous_z), Vector(0, 0, 1))
         cp = plane.intersect_point(line.dir, line.p1)[0]
         # we can be sure that there is an intersection
         if line.p1.z > previous_z:
             p1, p2 = cp, line.p2
         else:
             p1, p2 = line.p1, cp
         self.GenerateToolPathLinePush(pa, Line(p1, p2), z, previous_z,
                 draw_callback=draw_callback)
     else:
         if line.maxz <= z:
             # the line is completely below z
             p1 = Point(line.p1.x, line.p1.y, z)
             p2 = Point(line.p2.x, line.p2.y, z)
         elif line.minz >= z:
             p1 = line.p1
             p2 = line.p2
         else:
             log.warn("Unexpected condition EC_GTPLP: %s / %s / %s / %s" % \
                     (line.p1, line.p2, z, previous_z))
             return
         # no model -> no possible obstacles
         # model is completely below z (e.g. support bridges) -> no obstacles
         relevant_models = [m for m in self.models if m.maxz >= z]
         if not relevant_models:
             points = [p1, p2]
         elif self.physics:
             points = get_free_paths_ode(self.physics, p1, p2)
         else:
             points = get_free_paths_triangles(relevant_models, self.cutter,
                     p1, p2)
         if points:
             for point in points:
                 pa.append(point)
             if draw_callback:
                 draw_callback(tool_position=points[-1], toolpath=pa.paths)
コード例 #24
0
 def GenerateToolPathLinePush(self, pa, line, z, previous_z,
         draw_callback=None):
     if previous_z <= line.minz:
         # the line is completely above the previous level
         pass
     elif line.minz < z < line.maxz:
         # Split the line at the point at z level and do the calculation
         # for both point pairs.
         factor = (z - line.p1.z) / (line.p2.z - line.p1.z)
         plane_point = line.p1.add(line.vector.mul(factor))
         self.GenerateToolPathLinePush(pa, Line(line.p1, plane_point), z,
                 previous_z, draw_callback=draw_callback)
         self.GenerateToolPathLinePush(pa, Line(plane_point, line.p2), z,
                 previous_z, draw_callback=draw_callback)
     elif line.minz < previous_z < line.maxz:
         plane = Plane(Point(0, 0, previous_z), Vector(0, 0, 1))
         cp = plane.intersect_point(line.dir, line.p1)[0]
         # we can be sure that there is an intersection
         if line.p1.z > previous_z:
             p1, p2 = cp, line.p2
         else:
             p1, p2 = line.p1, cp
         self.GenerateToolPathLinePush(pa, Line(p1, p2), z, previous_z,
                 draw_callback=draw_callback)
     else:
         if line.maxz <= z:
             # the line is completely below z
             p1 = Point(line.p1.x, line.p1.y, z)
             p2 = Point(line.p2.x, line.p2.y, z)
         elif line.minz >= z:
             p1 = line.p1
             p2 = line.p2
         else:
             log.warn("Unexpected condition EC_GTPLP: %s / %s / %s / %s" % \
                     (line.p1, line.p2, z, previous_z))
             return
         # no model -> no possible obstacles
         # model is completely below z (e.g. support bridges) -> no obstacles
         relevant_models = [m for m in self.models if m.maxz >= z]
         if not relevant_models:
             points = [p1, p2]
         elif self.physics:
             points = get_free_paths_ode(self.physics, p1, p2)
         else:
             points = get_free_paths_triangles(relevant_models, self.cutter,
                     p1, p2)
         if points:
             for point in points:
                 pa.append(point)
             if draw_callback:
                 draw_callback(tool_position=points[-1], toolpath=pa.paths)
コード例 #25
0
 def get_barycenter(self):
     area = self.get_area()
     if not area:
         return None
     # see: http://stackoverflow.com/questions/2355931/foo/2360507
     # first: calculate cx and y
     cxy, cxz, cyx, cyz, czx, czy = (0, 0, 0, 0, 0, 0)
     for index in range(len(self._points)):
         p1 = self._points[index]
         p2 = self._points[(index + 1) % len(self._points)]
         cxy += (p1[0] + p2[0]) * (p1[0] * p2[1] - p1[1] * p2[0])
         cxz += (p1[0] + p2[0]) * (p1[0] * p2[2] - p1[2] * p2[0])
         cyx += (p1[1] + p2[1]) * (p1[0] * p2[1] - p1[1] * p2[0])
         cyz += (p1[1] + p2[1]) * (p1[1] * p2[2] - p1[2] * p2[1])
         czx += (p1[2] + p2[2]) * (p1[2] * p2[0] - p1[0] * p2[2])
         czy += (p1[2] + p2[2]) * (p1[1] * p2[2] - p1[2] * p2[1])
     if abs(self.maxz - self.minz) < epsilon:
         return (cxy / (6 * area), cyx / (6 * area), self.minz)
     elif abs(self.maxy - self.miny) < epsilon:
         return (cxz / (6 * area), self.miny, czx / (6 * area))
     elif abs(self.maxx - self.minx) < epsilon:
         return (self.minx, cyz / (6 * area), czy / (6 * area))
     else:
         # calculate area of xy projection
         poly_xy = self.get_plane_projection(Plane((0, 0, 0), (0, 0, 1)))
         poly_xz = self.get_plane_projection(Plane((0, 0, 0), (0, 1, 0)))
         poly_yz = self.get_plane_projection(Plane((0, 0, 0), (1, 0, 0)))
         if (poly_xy is None) or (poly_xz is None) or (poly_yz is None):
             log.warn("Invalid polygon projection for barycenter: %s",
                      str(self))
             return None
         area_xy = poly_xy.get_area()
         area_xz = poly_xz.get_area()
         area_yz = poly_yz.get_area()
         if 0 in (area_xy, area_xz, area_yz):
             log.info(
                 "Failed assumtion: zero-sized projected area - %s / %s / %s",
                 area_xy, area_xz, area_yz)
             return None
         if abs(cxy / area_xy - cxz / area_xz) > epsilon:
             log.info("Failed assumption: barycenter xy/xz - %s / %s",
                      cxy / area_xy, cxz / area_xz)
         if abs(cyx / area_xy - cyz / area_yz) > epsilon:
             log.info("Failed assumption: barycenter yx/yz - %s / %s",
                      cyx / area_xy, cyz / area_yz)
         if abs(czx / area_xz - czy / area_yz) > epsilon:
             log.info("Failed assumption: barycenter zx/zy - %s / %s",
                      czx / area_xz, cyz / area_yz)
         return (cxy / (6 * area_xy), cyx / (6 * area_xy),
                 czx / (6 * area_xz))
コード例 #26
0
ファイル: common.py プロジェクト: signotheque/pycam
 def __init__(self, title, message):
     try:
         import Tkinter
     except ImportError:
         # tk is not installed
         log.warn("Failed to show error dialog due to a missing Tkinter " \
                 + "Python package.")
         return
     try:
         root = Tkinter.Tk()
     except Tkinter.TclError, err_msg:
         log.info(("Failed to create error dialog window (%s). Probably " \
                 + "you are running PyCAM from a terminal.") % err_msg)
         return
コード例 #27
0
ファイル: pycampy.py プロジェクト: chriskyfung/MakerDroid
def load_model_file(filename, program_locations, unit=None):
    uri = pycam.Utils.URIHandler(filename)
    if uri.is_local():
        uri = pycam.Utils.URIHandler(os.path.expanduser(str(filename)))
    if not uri.exists():
        log.warn("The input file ('%s') was not found!" % uri)
        return None
    importer = pycam.Importers.detect_file_type(uri)[1]
    model = importer(uri, program_locations=program_locations, unit=unit)
    if not model:
        log.warn("Failed to load the model file (%s)." % uri)
        return None
    else:
        return model
コード例 #28
0
ファイル: pycam.py プロジェクト: petervanderwalt/pycam-cloud
def load_model_file(filename, program_locations, unit=None):
    uri = pycam.Utils.URIHandler(filename)
    if uri.is_local():
        uri = pycam.Utils.URIHandler(os.path.expanduser(str(filename)))
    if not uri.exists():
        log.warn("The input file ('%s') was not found!" % uri)
        return None
    importer = pycam.Importers.detect_file_type(uri)[1]
    model = importer(uri, program_locations=program_locations, unit=unit)
    if not model:
        log.warn("Failed to load the model file (%s)." % uri)
        return None
    else:
        return model
コード例 #29
0
 def _read_key_value(self):
     if self._input_stack:
         return self._input_stack.pop()
     try:
         line1 = self.inputstream.readline(self.MAX_CHARS_PER_LINE).strip()
         line2 = self.inputstream.readline(self.MAX_CHARS_PER_LINE).strip()
     except IOError:
         return None, None
     if not line1 and not line2:
         return None, None
     try:
         line1 = int(line1)
     except ValueError:
         log.warn("DXFImporter: Invalid key in line %d (int expected): %s",
                  self.line_number, line1)
         return None, None
     if line1 in [
             self.KEYS[key]
             for key in ("P1_X", "P1_Y", "P1_Z", "P2_X", "P2_Y", "P2_Z",
                         "RADIUS", "ANGLE_START", "ANGLE_END",
                         "TEXT_HEIGHT", "TEXT_WIDTH_FINAL", "TEXT_ROTATION",
                         "TEXT_SKEW_ANGLE", "VERTEX_BULGE")
     ]:
         try:
             line2 = float(line2)
         except ValueError:
             log.warn(
                 "DXFImporter: Invalid input in line %d (float expected): %s",
                 self.line_number, line2)
             line1 = None
             line2 = None
     elif line1 in [
             self.KEYS[key]
             for key in ("COLOR", "TEXT_MIRROR_FLAGS",
                         "TEXT_ALIGN_HORIZONTAL", "TEXT_ALIGN_VERTICAL",
                         "MTEXT_ALIGNMENT", "CURVE_TYPE", "VERTEX_FLAGS")
     ]:
         try:
             line2 = int(line2)
         except ValueError:
             log.warn(
                 "DXFImporter: Invalid input in line %d (int expected): %s",
                 self.line_number, line2)
             line1 = None
             line2 = None
     elif line1 in [self.KEYS[key] for key in ("DEFAULT", "TEXT_MORE")]:
         # check the string for invalid characters
         try:
             text = line2.decode("utf")
         except UnicodeDecodeError:
             log.warn("DXFImporter: Invalid character in string in line %d",
                      self.line_number)
             text = line2.decode("utf", errors="ignore")
         line2 = _unescape_control_characters(text)
     else:
         line2 = line2.upper()
     self.line_number += 2
     return line1, line2
コード例 #30
0
ファイル: Polygon.py プロジェクト: yummyburger/pycam
 def get_plane_projection(self, plane):
     if plane == self.plane:
         return self
     elif pdot(plane.n, self.plane.n) == 0:
         log.warn("Polygon projection onto plane: orthogonal projection is not possible")
         return None
     else:
         result = Polygon(plane)
         for line in self.get_lines():
             p1 = plane.get_point_projection(line.p1)
             p2 = plane.get_point_projection(line.p2)
             result.append(Line(p1, p2))
         # check if the projection would revert the direction of the polygon
         if pdot(plane.n, self.plane.n) < 0:
             result.reverse_direction()
         return result
コード例 #31
0
ファイル: DXFImporter.py プロジェクト: I--Fox--I/pycam
 def _read_key_value(self):
     if self._input_stack:
         return self._input_stack.pop()
     try:
         line1 = self.inputstream.readline(self.MAX_CHARS_PER_LINE).strip()
         line2 = self.inputstream.readline(self.MAX_CHARS_PER_LINE).strip()
     except IOError:
         return None, None
     if not line1 and not line2:
         return None, None
     try:
         line1 = int(line1)
     except ValueError:
         log.warn("DXFImporter: Invalid key in line " \
                 + "%d (int expected): %s" % (self.line_number, line1))
         return None, None
     if line1 in [self.KEYS[key] for key in ("P1_X", "P1_Y", "P1_Z",
             "P2_X", "P2_Y", "P2_Z", "RADIUS", "ANGLE_START", "ANGLE_END",
             "TEXT_HEIGHT", "TEXT_WIDTH_FINAL", "TEXT_ROTATION",
             "TEXT_SKEW_ANGLE", "VERTEX_BULGE")]:
         try:
             line2 = float(line2)
         except ValueError:
             log.warn("DXFImporter: Invalid input in line " \
                     + "%d (float expected): %s" % (self.line_number, line2))
             line1 = None
             line2 = None
     elif line1 in [self.KEYS[key] for key in ("COLOR", "TEXT_MIRROR_FLAGS",
             "TEXT_ALIGN_HORIZONTAL", "TEXT_ALIGN_VERTICAL",
             "MTEXT_ALIGNMENT", "CURVE_TYPE", "VERTEX_FLAGS")]:
         try:
             line2 = int(line2)
         except ValueError:
             log.warn("DXFImporter: Invalid input in line " \
                     + "%d (int expected): %s" % (self.line_number, line2))
             line1 = None
             line2 = None
     elif line1 in [self.KEYS[key] for key in ("DEFAULT", "TEXT_MORE")]:
         # check the string for invalid characters
         try:
             text = unicode(line2)
         except UnicodeDecodeError:
             log.warn("DXFImporter: Invalid character in string in " + \
                     "line %d" % self.line_number)
             text_chars = []
             for char in line2:
                 try:
                     text_chars.append(unicode(char))
                 except:
                     pass
             text = u"".join(text_chars)
         line2 = _unescape_control_characters(text)
     else:
         line2 = line2.upper()
     self.line_number += 2
     return line1, line2
コード例 #32
0
 def parse_line(self):
     start_line = self.line_number
     # the z-level defaults to zero (for 2D models)
     p1 = [None, None, 0]
     p2 = [None, None, 0]
     color = None
     key, value = self._read_key_value()
     while (key is not None) and (key != self.KEYS["MARKER"]):
         if key == self.KEYS["P1_X"]:
             p1[0] = value
         elif key == self.KEYS["P1_Y"]:
             p1[1] = value
         elif key == self.KEYS["P1_Z"]:
             p1[2] = value
         elif key == self.KEYS["P2_X"]:
             p2[0] = value
         elif key == self.KEYS["P2_Y"]:
             p2[1] = value
         elif key == self.KEYS["P2_Z"]:
             p2[2] = value
         elif key == self.KEYS["COLOR"]:
             color = value
         else:
             pass
         key, value = self._read_key_value()
     end_line = self.line_number
     # The last lines were not used - they are just the marker for the next
     # item.
     if key is not None:
         self._push_on_stack(key, value)
     if (None in p1) or (None in p2):
         log.warn(
             "DXFImporter: Incomplete LINE definition between line %d and %d",
             start_line, end_line)
     else:
         if self._color_as_height and (color is not None):
             # use the color code as the z coordinate
             p1[2] = float(color) / 255
             p2[2] = float(color) / 255
         line = Line((p1[0], p1[1], p1[2]), (p2[0], p2[1], p2[2]))
         if line.p1 != line.p2:
             self.lines.append(line)
         else:
             log.warn(
                 "DXFImporter: Ignoring zero-length LINE (between input line %d and %d): "
                 "%s", start_line, end_line, line)
コード例 #33
0
ファイル: DXFImporter.py プロジェクト: I--Fox--I/pycam
 def parse_line(self):
     start_line = self.line_number
     # the z-level defaults to zero (for 2D models)
     p1 = [None, None, 0]
     p2 = [None, None, 0]
     color = None
     key, value = self._read_key_value()
     while (not key is None) and (key != self.KEYS["MARKER"]):
         if key == self.KEYS["P1_X"]:
             p1[0] = value
         elif key == self.KEYS["P1_Y"]:
             p1[1] = value
         elif key == self.KEYS["P1_Z"]:
             p1[2] = value
         elif key == self.KEYS["P2_X"]:
             p2[0] = value
         elif key == self.KEYS["P2_Y"]:
             p2[1] = value
         elif key == self.KEYS["P2_Z"]:
             p2[2] = value
         elif key == self.KEYS["COLOR"]:
             color = value
         else:
             pass
         key, value = self._read_key_value()
     end_line = self.line_number
     # The last lines were not used - they are just the marker for the next
     # item.
     if not key is None:
         self._push_on_stack(key, value)
     if (None in p1) or (None in p2):
         log.warn("DXFImporter: Incomplete LINE definition between line " \
                 + "%d and %d" % (start_line, end_line))
     else:
         if self._color_as_height and (not color is None):
             # use the color code as the z coordinate
             p1[2] = float(color) / 255
             p2[2] = float(color) / 255
         line = Line(Point(p1[0], p1[1], p1[2]), Point(p2[0], p2[1], p2[2]))
         if line.p1 != line.p2:
             self.lines.append(line)
         else:
             log.warn("DXFImporter: Ignoring zero-length LINE (between " \
                     + "input line %d and %d): %s" % (start_line, end_line,
                     line))
コード例 #34
0
ファイル: Project.py プロジェクト: I--Fox--I/pycam
 def save_preferences(self):
     """ save all settings that are available in the Preferences window to
     a file in the user's home directory """
     config_filename = pycam.Gui.Settings.get_config_filename()
     if config_filename is None:
         # failed to create the personal preferences directory
         log.warn("Failed to create a preferences directory in " \
                 + "your user's home directory.")
         return
     config = ConfigParser.ConfigParser()
     for item in PREFERENCES_DEFAULTS.keys():
         config.set("DEFAULT", item, self.settings.get(item))
     try:
         config_file = file(config_filename, "w")
         config.write(config_file)
         config_file.close()
     except IOError, err_msg:
         log.warn("Failed to write preferences file (%s): %s" % (config_filename, err_msg))
コード例 #35
0
def parse_toolpath_settings(filename):
    """ parse potential PyCAM settings from a given file

    This is mainly useful to retrieve task settings from a GCode file.
    @value filename: the name of the file to be read
    @type filename: str
    @returns: a dictionary (of all setting names and values) and the content
            of the 'comment' section (as a single string)
    @rtype: tuple(dict, str)
    """
    keywords = {}
    in_meta_zone = False
    meta_content = []
    if filename == "-":
        # read from stdin, if the input filename is "-"
        infile = sys.stdin
        close_file = False
    else:
        # open the file
        try:
            infile = pycam.Utils.URIHandler(filename).open()
        except IOError as err_msg:
            log.warn("ToolpathSettingsParser: Failed to read file (%s): %s",
                     filename, err_msg)
            return None
        close_file = True
    for line in infile.readlines():
        match = re.match(REGEX_META_KEYWORDS, line)
        if match:
            keywords[match.groups()[0]] = match.groups()[1].strip()
        if in_meta_zone:
            if re.match(REGEX_SETTINGS_END, line):
                in_meta_zone = False
            else:
                if line and line[0] in COMMENT_CHARACTERS:
                    meta_content[-1].append(line[1:].strip())
        else:
            if re.match(REGEX_SETTINGS_START, line):
                in_meta_zone = True
                meta_content.append([])
    if close_file:
        # only close the file if it was opened before (e.g. not stdin)
        infile.close()
    return keywords, [os.linesep.join(one_block) for one_block in meta_content]
コード例 #36
0
ファイル: Project.py プロジェクト: signotheque/pycam
 def save_preferences(self):
     """ save all settings that are available in the Preferences window to
     a file in the user's home directory """
     config_filename = pycam.Gui.Settings.get_config_filename()
     if config_filename is None:
         # failed to create the personal preferences directory
         log.warn("Failed to create a preferences directory in " \
                 + "your user's home directory.")
         return
     config = ConfigParser.ConfigParser()
     for item in PREFERENCES_DEFAULTS.keys():
         config.set("DEFAULT", item, self.settings.get(item))
     try:
         config_file = file(config_filename, "w")
         config.write(config_file)
         config_file.close()
     except IOError, err_msg:
         log.warn("Failed to write preferences file (%s): %s" %
                  (config_filename, err_msg))
コード例 #37
0
ファイル: Settings.py プロジェクト: yummyburger/pycam
def get_config_dirname():
    try:
        from win32com.shell import shellcon, shell
        homedir = shell.SHGetFolderPath(0, shellcon.CSIDL_APPDATA, 0, 0)
        config_dir = os.path.join(homedir, CONFIG_DIR)
    except ImportError:
        # quick semi-nasty fallback for non-windows/win32com case
        homedir = os.path.expanduser("~")
        # hide the config directory for unixes
        config_dir = os.path.join(homedir, "." + CONFIG_DIR)
    if not os.path.isdir(config_dir):
        try:
            os.makedirs(config_dir)
        except OSError:
            log.warn(
                "Failed to create preferences directory in your user's home directory: %s",
                config_dir)
            config_dir = None
    return config_dir
コード例 #38
0
def import_font(filename, callback=None):
    try:
        infile = pycam.Utils.URIHandler(filename).open()
    except IOError as err_msg:
        log.error("CXFImporter: Failed to read file (%s): %s", filename,
                  err_msg)
        return None
    try:
        parsed_font = CXFParser(infile, callback=callback)
    except _CXFParseError as err_msg:
        log.warn("CFXImporter: Skipped font defintion file '%s'. Reason: %s.",
                 filename, err_msg)
        return None
    charset = Charset(**parsed_font.meta)
    for key, value in parsed_font.letters.iteritems():
        charset.add_character(key, value)
    log.info("CXFImporter: Imported CXF font from '%s': %d letters", filename,
             len(parsed_font.letters))
    infile.close()
    return charset
コード例 #39
0
 def parse_content(self):
     key, value = self._read_key_value()
     while (key is not None) and not ((key == self.KEYS["MARKER"]) and
                                      (value == "EOF")):
         if self.callback and self.callback():
             return
         if key == self.KEYS["MARKER"]:
             if value in ("SECTION", "TABLE", "LAYER", "ENDTAB", "ENDSEC"):
                 # we don't handle these meta-information
                 pass
             elif value == "LINE":
                 self.parse_line()
             elif value == "LWPOLYLINE":
                 self.parse_lwpolyline()
             elif value == "POLYLINE":
                 self.parse_polyline(True)
             elif value == "VERTEX":
                 self.parse_vertex()
             elif value == "SEQEND":
                 self.close_sequence()
             elif value == "ARC":
                 self.parse_arc()
             elif value == "CIRCLE":
                 self.parse_arc(circle=True)
             elif value == "TEXT":
                 self.parse_text()
             elif value == "MTEXT":
                 self.parse_mtext()
             elif value == "3DFACE":
                 self.parse_3dface()
             elif value in self.IGNORE_KEYS:
                 log.debug(
                     "DXFImporter: Ignored a blacklisted element in line %d: %s",
                     self.line_number, value)
             else:
                 # not supported
                 log.warn(
                     "DXFImporter: Ignored unsupported element in line %d: %s",
                     self.line_number, value)
         key, value = self._read_key_value()
コード例 #40
0
 def load_preferences(self):
     """ load all settings (see Preferences window) from a file in the user's home directory """
     config = ConfigParser()
     try:
         with pycam.Gui.Settings.open_preferences_file() as in_file:
             config.read_file(in_file)
     except FileNotFoundError as exc:
         log.info(
             "No preferences file found (%s). Starting with default preferences.",
             exc)
     except OSError as exc:
         log.error("Failed to read preferences: %s", exc)
         return
     # report any ignored (obsolete) preference keys present in the file
     for item, value in config.items("DEFAULT"):
         if item not in PREFERENCES_DEFAULTS.keys():
             log.warn("Skipping obsolete preference item: %s", str(item))
     for item in PREFERENCES_DEFAULTS:
         if not config.has_option("DEFAULT", item):
             # a new preference setting is missing in the (old) file
             continue
         value_json = config.get("DEFAULT", item)
         try:
             value = json.loads(value_json)
         except ValueError as exc:
             log.warning("Failed to parse configuration setting '%s': %s",
                         item, exc)
             value = PREFERENCES_DEFAULTS[item]
         wanted_type = type(PREFERENCES_DEFAULTS[item])
         if wanted_type is float:
             # int is accepted for floats, too
             wanted_type = (float, int)
         if not isinstance(value, wanted_type):
             log.warning(
                 "Falling back to default configuration setting for '%s' due to "
                 "an invalid value type being parsed: %s != %s", item,
                 type(value), wanted_type)
             value = PREFERENCES_DEFAULTS[item]
         self.settings.set(item, value)
コード例 #41
0
ファイル: DXFImporter.py プロジェクト: I--Fox--I/pycam
 def parse_content(self):
     key, value = self._read_key_value()
     while (not key is None) \
             and not ((key == self.KEYS["MARKER"]) and (value == "EOF")):
         if self.callback and self.callback():
             return
         if key == self.KEYS["MARKER"]:
             if value in ("SECTION", "TABLE", "LAYER", "ENDTAB", "ENDSEC"):
                 # we don't handle these meta-information
                 pass
             elif value == "LINE":
                 self.parse_line()
             elif value == "LWPOLYLINE":
                 self.parse_lwpolyline()
             elif value == "POLYLINE":
                 self.parse_polyline(True)
             elif value == "VERTEX":
                 self.parse_vertex()
             elif value == "SEQEND":
                 self.close_sequence()
             elif value == "ARC":
                 self.parse_arc()
             elif value == "CIRCLE":
                 self.parse_arc(circle=True)
             elif value == "TEXT":
                 self.parse_text()
             elif value == "MTEXT":
                 self.parse_mtext()
             elif value == "3DFACE":
                 self.parse_3dface()
             elif value in self.IGNORE_KEYS:
                 log.debug("DXFImporter: Ignored a blacklisted element " \
                         + "in line %d: %s" % (self.line_number, value))
             else:
                 # not supported
                 log.warn("DXFImporter: Ignored unsupported element " \
                         + "in line %d: %s" % (self.line_number, value))
         key, value = self._read_key_value()
コード例 #42
0
def recommends_details_gtk():
    result = {}
    try:
        import gtk.gtkgl  # noqa F401
        result["gtkgl"] = True
        result["gl"] = True
    except ImportError as err_msg:
        log.warn("Failed to import OpenGL for GTK (ImportError): %s", str(err_msg))
        result["gtkgl"] = False
    except RuntimeError as err_msg:
        log.warn("Failed to import OpenGL for GTK (RuntimeError): %s", str(err_msg))
        result["gl"] = False
    try:
        import OpenGL  # noqa F401
        result["opengl"] = True
    except ImportError as err_msg:
        log.warn("Failed to import OpenGL: %s", str(err_msg))
        result["opengl"] = False
コード例 #43
0
ファイル: locations.py プロジェクト: valeriob01/pycam
def get_font_dir():
    if FONT_DIR_OVERRIDE:
        if os.path.isdir(FONT_DIR_OVERRIDE):
            return FONT_DIR_OVERRIDE
        else:
            log.warn("You specified a font dir that does not exist (%s). I will ignore it.",
                     FONT_DIR_OVERRIDE)
    font_dir = get_data_file_location(FONTS_SUBDIR, silent=True)
    if font_dir is not None:
        return font_dir
    else:
        log.warn("Failed to locate the fonts directory '%s' below '%s'. Falling back to '%s'.",
                 FONTS_SUBDIR, DATA_BASE_DIRS, ":".join(FONT_DIRS_FALLBACK))
        for font_dir_fallback in FONT_DIRS_FALLBACK:
            if os.path.isdir(font_dir_fallback):
                return font_dir_fallback
        log.warn("None of the fallback font directories (%s) exist. No fonts will be available.",
                 ":".join(FONT_DIRS_FALLBACK))
        return None
コード例 #44
0
ファイル: locations.py プロジェクト: michaelr123/pycam
def get_font_dir():
    if FONT_DIR_OVERRIDE:
        if os.path.isdir(FONT_DIR_OVERRIDE):
            return FONT_DIR_OVERRIDE
        else:
            log.warn(("You specified a font dir that does not exist (%s). " + "I will ignore it.") % FONT_DIR_OVERRIDE)
    font_dir = get_data_file_location(FONTS_SUBDIR, silent=True)
    if not font_dir is None:
        return font_dir
    else:
        log.warn(
            ("Failed to locate the fonts directory '%s' below '%s'. " + "Falling back to '%s'.")
            % (FONTS_SUBDIR, DATA_BASE_DIRS, ":".join(FONT_DIRS_FALLBACK))
        )
        for font_dir_fallback in FONT_DIRS_FALLBACK:
            if os.path.isdir(font_dir_fallback):
                return font_dir_fallback
        else:
            log.warn(
                ("None of the fallback font directories (%s) exist. " + "No fonts will be available.")
                % ":".join(FONT_DIRS_FALLBACK)
            )
            return None
コード例 #45
0
ファイル: STLImporter.py プロジェクト: stevegt/pycam
        log.error("STLImporter: STL binary/ascii detection failed")
        return None

    if use_kdtree:
        kdtree = PointKdtree([], 3, 1, epsilon)
    model = Model(use_kdtree)

    t = None
    p1 = None
    p2 = None
    p3 = None

    if binary:
        for i in range(1, numfacets + 1): 
            if callback and callback():
                log.warn("STLImporter: load model operation cancelled")
                return None
            a1 = unpack("<f", f.read(4))[0] 
            a2 = unpack("<f", f.read(4))[0] 
            a3 = unpack("<f", f.read(4))[0] 

            n = (float(a1), float(a2), float(a3), 'v')
            
            v11 = unpack("<f", f.read(4))[0] 
            v12 = unpack("<f", f.read(4))[0] 
            v13 = unpack("<f", f.read(4))[0] 

            p1 = UniqueVertex(float(v11), float(v12), float(v13))
            
            v21 = unpack("<f", f.read(4))[0] 
            v22 = unpack("<f", f.read(4))[0] 
コード例 #46
0
ファイル: DXFImporter.py プロジェクト: I--Fox--I/pycam
 def parse_text(self):
     start_line = self.line_number
     # the z-level defaults to zero (for 2D models)
     ref_point = [None, None, 0]
     ref_point2 = [None, None, 0]
     color = None
     text = None
     text_height = None
     rotation = 0
     width_final = None
     skew_angle = 0
     font_name = "normal"
     mirror_flags = 0
     align_horiz = 0
     align_vert = 0
     key, value = self._read_key_value()
     while (not key is None) and (key != self.KEYS["MARKER"]):
         if key == self.KEYS["DEFAULT"]:
             text = value
         elif key == self.KEYS["P1_X"]:
             ref_point[0] = value
         elif key == self.KEYS["P1_Y"]:
             ref_point[1] = value
         elif key == self.KEYS["P1_Z"]:
             ref_point[2] = value
         elif key == self.KEYS["P2_X"]:
             ref_point2[0] = value
         elif key == self.KEYS["P2_Y"]:
             ref_point2[1] = value
         elif key == self.KEYS["P2_Z"]:
             ref_point2[2] = value
         elif key == self.KEYS["COLOR"]:
             color = value
         elif key == self.KEYS["TEXT_HEIGHT"]:
             text_height = value
         elif key == self.KEYS["TEXT_ROTATION"]:
             rotation = value
         elif key == self.KEYS["TEXT_SKEW_ANGLE"]:
             skew_angle = value
         elif key == self.KEYS["TEXT_FONT"]:
             font_name = value
         elif key == self.KEYS["TEXT_MIRROR_FLAGS"]:
             mirror_flags = value
         elif key == self.KEYS["TEXT_ALIGN_HORIZONTAL"]:
             align_horiz = value
         elif key == self.KEYS["TEXT_ALIGN_VERTICAL"]:
             align_vert = value
         elif key == self.KEYS["TEXT_WIDTH_FINAL"]:
             width_final = value
         else:
             pass
         key, value = self._read_key_value()
     end_line = self.line_number
     # The last lines were not used - they are just the marker for the next
     # item.
     if not key is None:
         self._push_on_stack(key, value)
     if (not None in ref_point2) and (ref_point != ref_point2):
         # just a warning - continue as usual
         log.warn("DXFImporter: Second alignment point is not " + \
                 "implemented for TEXT items - the text specified " + \
                 "between line %d and %d may be slightly misplaced" % \
                 (start_line, end_line))
     if None in ref_point:
         log.warn("DXFImporter: Incomplete TEXT definition between line " \
                 + "%d and %d: missing location point" % \
                 (start_line, end_line))
     elif not text:
         log.warn("DXFImporter: Incomplete TEXT definition between line " \
                 + "%d and %d: missing text" % (start_line, end_line))
     elif not text_height:
         log.warn("DXFImporter: Incomplete TEXT definition between line " \
                 + "%d and %d: missing height" % (start_line, end_line))
     else:
         if self._color_as_height and (not color is None):
             # use the color code as the z coordinate
             ref_point[2] = float(color) / 255
         if self._fonts_cache:
             font = self._fonts_cache.get_font(font_name)
         else:
             font = None
         if not font:
             log.warn("DXFImporter: No fonts are available - skipping " + \
                     "TEXT item between line %d and %d" % \
                     (start_line, end_line))
             return
         if skew_angle:
             # calculate the "skew" factor
             if (skew_angle <= -90) or (skew_angle >= 90):
                 log.warn("DXFImporter: Invalid skew angle for TEXT " + \
                         "between line %d and %d" % (start_line, end_line))
                 skew = 0
             else:
                 skew = math.tan(skew_angle)
         else:
             skew = 0
         model = font.render(text, skew=skew)
         if (model.minx is None) or (model.miny is None) or \
                 (model.minz is None) or (model.minx == model.maxx) or \
                 (model.miny == model.maxy):
             log.warn("DXFImporter: Empty rendered TEXT item between " + \
                     "line %d and %d" % (start_line, end_line))
             return
         model.scale(text_height / (model.maxy - model.miny),
                 callback=self.callback)
         if mirror_flags & 2:
             # x mirror left/right
             model.transform_by_template("yz_mirror", callback=self.callback)
         if mirror_flags & 4:
             # y mirror upside/down
             model.transform_by_template("xz_mirror", callback=self.callback)
         # this setting seems to refer to a box - not the text width - ignore
         if False and width_final:
             scale_x = width_final / (model.maxx - model.minx)
             model.scale(scale_x, callback=self.callback)
         if rotation:
             matrix = pycam.Geometry.Matrix.get_rotation_matrix_axis_angle(
                     (0, 0, 1), rotation)
             model.transform_by_matrix(matrix, callback=self.callback)
         # horizontal alignment
         if align_horiz == 0:
             offset_horiz = 0
         elif align_horiz == 1:
             offset_horiz = - (model.maxx - model.minx) / 2
         elif align_horiz == 2:
             offset_horiz = - (model.maxx - model.minx)
         else:
             log.warn("DXFImporter: Horizontal TEXT justifications " + \
                     "(3..5) are not supported - ignoring (between line " + \
                     "%d and %d)" % (start_line, end_line))
             offset_horiz = 0
         # vertical alignment
         if align_vert in (0, 1):
             # we don't distinguish between "bottom" and "base"
             offset_vert = 0
         elif align_vert == 2:
             offset_vert = - (model.maxy - model.miny) / 2
         elif align_vert == 3:
             offset_vert = - (model.maxy - model.miny)
         else:
             log.warn("DXFImporter: Invalid vertical TEXT justification " + \
                     " between line %d and %d" % (start_line, end_line))
             offset_vert = 0
         # shift the text to its final destination
         shift_x = ref_point[0] - model.minx + offset_horiz
         shift_y = ref_point[1] - model.miny + offset_vert
         shift_z = ref_point[2] - model.minz
         model.shift(shift_x, shift_y, shift_z, callback=self.callback)
         for polygon in model.get_polygons():
             for line in polygon.get_lines():
                 self.lines.append(line)
コード例 #47
0
def import_model(filename,
                 color_as_height=False,
                 fonts_cache=None,
                 callback=None,
                 **kwargs):
    if hasattr(filename, "read"):
        infile = filename
    else:
        try:
            infile = pycam.Utils.URIHandler(filename).open()
        except IOError as exc:
            raise LoadFileError(
                "DXFImporter: Failed to read file ({}): {}".format(
                    filename, exc))

    result = DXFParser(infile,
                       color_as_height=color_as_height,
                       fonts_cache=fonts_cache,
                       callback=callback)

    model_data = result.get_model()
    lines = model_data["lines"]
    triangles = model_data["triangles"]

    if callback and callback():
        raise AbortOperationException(
            "DXFImporter: load model operation was cancelled")

    # 3D models are preferred over 2D models
    if triangles:
        if lines:
            log.warn("DXFImporter: Ignoring 2D elements in DXF file: %d lines",
                     len(lines))
        model = pycam.Geometry.Model.Model()
        for index, triangle in enumerate(triangles):
            model.append(triangle)
            # keep the GUI smooth
            if callback and (index % 50 == 0):
                callback()
        log.info("DXFImporter: Imported DXF model (3D): %d triangles",
                 len(model.triangles()))
        return model
    elif lines:
        model = pycam.Geometry.Model.ContourModel()
        for index, line in enumerate(lines):
            model.append(line)
            # keep the GUI smooth
            if callback and (index % 50 == 0):
                callback()
        # z scaling is always targeted at the 0..1 range
        if color_as_height and (model.minz != model.maxz):
            # scale z to 1
            scale_z = 1.0 / (model.maxz - model.minz)
            if callback:
                callback(text="Scaling height for multi-layered 2D model")
            log.info("DXFImporter: scaling height for multi-layered 2D model")
            model.scale(scale_x=1.0,
                        scale_y=1.0,
                        scale_z=scale_z,
                        callback=callback)
        # shift the model down to z=0
        if model.minz != 0:
            if callback:
                callback(text="Shifting 2D model down to to z=0")
            model.shift(0, 0, -model.minz, callback=callback)
        log.info(
            "DXFImporter: Imported DXF model (2D): %d lines / %d polygons",
            len(lines), len(model.get_polygons()))
        return model
    else:
        link = "http://pycam.sourceforge.net/supported-formats"
        raise LoadFileError(
            'DXFImporter: No supported elements found in DXF file!\n'
            '<a href="%s">Read PyCAM\'s modeling hints.</a>'.format(link))
コード例 #48
0
ファイル: threading.py プロジェクト: chriskyfung/MakerDroid
def init_threading(number_of_processes=None, enable_server=False, remote=None,
        run_server=False, server_credentials="", local_port=DEFAULT_PORT):
    global __multiprocessing, __num_of_processes, __manager, __closing, \
            __task_source_uuid
    if __multiprocessing:
        # kill the manager and clean everything up for a re-initialization
        cleanup()
    if (not is_server_mode_available()) and (enable_server or run_server):
        # server mode is disabled for the Windows pyinstaller standalone
        # due to "pickle errors". How to reproduce: run the standalone binary
        # with "--enable-server --server-auth-key foo".
        feature_matrix_text = "Take a look at the wiki for a matrix of " + \
                "platforms and available features: " + \
                "http://sf.net/apps/mediawiki/pycam/?title=" + \
                "Parallel_Processing_on_different_Platforms"
        if enable_server:
            log.warn("Unable to enable server mode with your current " + \
                    "setup.\n" + feature_matrix_text)
        elif run_server:
            log.warn("Unable to run in server-only mode with the Windows " + \
                    "standalone executable.\n" + feature_matrix_text)
        else:
            # no further warnings required
            pass
        enable_server = False
        run_server = False
    # only local -> no server settings allowed
    if (not enable_server) and (not run_server):
        remote = None
        run_server = None
        server_credentials = ""
    try:
        import multiprocessing
        mp_is_available = True
    except ImportError:
        mp_is_available = False
    if not mp_is_available:
        __multiprocessing = False
        # Maybe a multiprocessing feature was explicitely requested?
        # Issue some warnings if necessary.
        multiprocessing_missing_text = "Failed to enable server mode due to " \
                + "a lack of 'multiprocessing' capabilities. Please use " \
                + "Python2.6 or install the 'python-multiprocessing' package."
        if enable_server:
            log.warn("Failed to enable server mode due to a lack of " \
                    + "'multiprocessing' capabilities. " \
                    + multiprocessing_missing_text)
        elif run_server:
            log.warn("Failed to run in server-only mode due to a lack of " \
                    + "'multiprocessing' capabilities. " \
                    + multiprocessing_missing_text)
        else:
            # no further warnings required
            pass
    else:
        if number_of_processes is None:
            # use defaults
            # don't enable threading for a single cpu
            if (multiprocessing.cpu_count() > 1) or remote or run_server or \
                    enable_server:
                __multiprocessing = multiprocessing
                __num_of_processes = multiprocessing.cpu_count()
            else:
                __multiprocessing = False
        elif (number_of_processes < 1) and (remote is None) and \
                (enable_server is None):
            # Zero processes are allowed if we use a remote server or offer a
            # server.
            __multiprocessing = False
        else:
            __multiprocessing = multiprocessing
            __num_of_processes = number_of_processes
    # initialize the manager
    if not __multiprocessing:
        __manager = None
        log.info("Disabled parallel processing")
    elif not enable_server and not run_server:
        __manager = None
        log.info("Enabled %d parallel local processes" % __num_of_processes)
    else:
        # with multiprocessing
        log.info("Enabled %d parallel local processes" % __num_of_processes)
        log.info("Allow remote processing")
        # initialize the uuid list for all workers
        worker_uuid_list = [str(uuid.uuid1())
                for index in range(__num_of_processes)]
        __task_source_uuid = str(uuid.uuid1())
        if remote is None:
            # try to guess an appropriate interface for binding
            if pycam.Utils.get_platform() == pycam.Utils.PLATFORM_WINDOWS:
                # Windows does not support a wildcard interface listener
                all_ips = pycam.Utils.get_all_ips()
                if all_ips:
                    address = (all_ips[0], local_port)
                    log.info("Binding to local interface with IP %s" % \
                            str(all_ips[0]))
                else:
                    return "Failed to find any local IP"
            else:
                # empty hostname -> wildcard interface
                # (this does not work with Windows - see above)
                address = ('', local_port)
        else:
            if ":" in remote:
                host, port = remote.split(":", 1)
                try:
                    port = int(port)
                except ValueError:
                    log.warning(("Invalid port specified: '%s' - using " + \
                            "default port (%d) instead") % \
                            (port, DEFAULT_PORT))
                    port = DEFAULT_PORT
            else:
                host = remote
                port = DEFAULT_PORT
            address = (host, port)
        if remote is None:
            tasks_queue = multiprocessing.Queue()
            results_queue = multiprocessing.Queue()
            statistics = ProcessStatistics()
            cache = ProcessDataCache()
            pending_tasks = PendingTasks()
            info = ManagerInfo(tasks_queue, results_queue, statistics, cache,
                    pending_tasks)
            TaskManager.register("tasks", callable=info.get_tasks_queue)
            TaskManager.register("results", callable=info.get_results_queue)
            TaskManager.register("statistics", callable=info.get_statistics)
            TaskManager.register("cache", callable=info.get_cache)
            TaskManager.register("pending_tasks",
                    callable=info.get_pending_tasks)
        else:
            TaskManager.register("tasks")
            TaskManager.register("results")
            TaskManager.register("statistics")
            TaskManager.register("cache")
            TaskManager.register("pending_tasks")
        __manager = TaskManager(address=address, authkey=server_credentials)
        # run the local server, connect to a remote one or begin serving
        try:
            if remote is None:
                __manager.start()
                log.info("Started a local server.")
            else:
                __manager.connect()
                log.info("Connected to a remote task server.")
        except (multiprocessing.AuthenticationError, socket.error), err_msg:
            __manager = None
            return err_msg
        except EOFError:
            __manager = None
            return "Failed to bind to socket for unknown reasons"
コード例 #49
0
ファイル: DXFImporter.py プロジェクト: I--Fox--I/pycam
 def parse_3dface(self):
     start_line = self.line_number
     # the z-level defaults to zero (for 2D models)
     p1 = [None, None, 0]
     p2 = [None, None, 0]
     p3 = [None, None, 0]
     p4 = [None, None, 0]
     color = None
     key, value = self._read_key_value()
     while (not key is None) and (key != self.KEYS["MARKER"]):
         if key == self.KEYS["P1_X"]:
             p1[0] = value
         elif key == self.KEYS["P1_Y"]:
             p1[1] = value
         elif key == self.KEYS["P1_Z"]:
             p1[2] = value
         elif key == self.KEYS["P2_X"]:
             p2[0] = value
         elif key == self.KEYS["P2_Y"]:
             p2[1] = value
         elif key == self.KEYS["P2_Z"]:
             p2[2] = value
         elif key == self.KEYS["P3_X"]:
             p3[0] = value
         elif key == self.KEYS["P3_Y"]:
             p3[1] = value
         elif key == self.KEYS["P3_Z"]:
             p3[2] = value
         elif key == self.KEYS["P4_X"]:
             p4[0] = value
         elif key == self.KEYS["P4_Y"]:
             p4[1] = value
         elif key == self.KEYS["P4_Z"]:
             p4[2] = value
         else:
             pass
         key, value = self._read_key_value()
     end_line = self.line_number
     # The last lines were not used - they are just the marker for the next
     # item.
     if not key is None:
         self._push_on_stack(key, value)
     if (None in p1) or (None in p2) or (None in p3):
         log.warn("DXFImporter: Incomplete 3DFACE definition between line " \
                 + "%d and %d" % (start_line, end_line))
     else:
         # no color height adjustment for 3DFACE
         point1 = Point(p1[0], p1[1], p1[2])
         point2 = Point(p2[0], p2[1], p2[2])
         point3 = Point(p3[0], p3[1], p3[2])
         triangles = []
         triangles.append((point1, point2, point3))
         # DXF specifies, that p3=p4 if triangles (instead of quads) are
         # written.
         if (not None in p4) and (p3 != p4):
             point4 = Point(p4[0], p4[1], p4[2])
             triangles.append((point3, point4, point1))
         for t in triangles:
             if (t[0] != t[1]) and (t[0] != t[2]) and (t[1] != t[2]):
                 self.triangles.append(Triangle(t[0], t[1], t[2]))
             else:
                 log.warn("DXFImporter: Ignoring zero-sized 3DFACE " + \
                         "(between input line %d and %d): %s" % \
                         (start_line, end_line, t))
コード例 #50
0
ファイル: common.py プロジェクト: I--Fox--I/pycam
        result["gtk"] = False
    return result


def recommends_details_gtk():
    result = {}
    try:
        import gtk.gtkgl
        result["gtkgl"] = True
        result["gl"] = True
    except ImportError, err_msg:
        log.warn("Failed to import OpenGL for GTK (ImportError): %s" % \
                str(err_msg))
        result["gtkgl"] = False
    except RuntimeError, err_msg:
        log.warn("Failed to import OpenGL for GTK (RuntimeError): %s" % \
                str(err_msg))
        result["gl"] = False
    try:
        import OpenGL
        result["opengl"] = True
    except ImportError, err_msg:
        log.warn("Failed to import OpenGL: %s" % str(err_msg))
        result["opengl"] = False


def check_dependencies(details):
    """you can feed this function with the output of
    '(requirements|recommends)_details_*'.
    The result is True if all dependencies are met.
    """
    failed = [key for (key, state) in details.items() if not state]
コード例 #51
0
ファイル: DXFImporter.py プロジェクト: I--Fox--I/pycam
 def parse_mtext(self):
     start_line = self.line_number
     # the z-level defaults to zero (for 2D models)
     ref_point = [None, None, 0]
     direction_vector = [None, None, None]
     color = None
     text_groups_start = []
     text_end = []
     text_height = None
     rotation = 0
     width_final = None
     font_name = "normal"
     alignment = 0
     key, value = self._read_key_value()
     while (not key is None) and (key != self.KEYS["MARKER"]):
         if key == self.KEYS["DEFAULT"]:
             text_end = value
         elif key == self.KEYS["TEXT_MORE"]:
             text_groups_start.append(value)
         elif key == self.KEYS["P1_X"]:
             ref_point[0] = value
         elif key == self.KEYS["P1_Y"]:
             ref_point[1] = value
         elif key == self.KEYS["P1_Z"]:
             ref_point[2] = value
         elif key == self.KEYS["P2_X"]:
             direction_vector[0] = value
             # according to DXF spec: the last one wins
             rotation = None
         elif key == self.KEYS["P2_Y"]:
             direction_vector[1] = value
             # according to DXF spec: the last one wins
             rotation = None
         elif key == self.KEYS["P2_Z"]:
             direction_vector[2] = value
             # according to DXF spec: the last one wins
             rotation = None
         elif key == self.KEYS["COLOR"]:
             color = value
         elif key == self.KEYS["TEXT_HEIGHT"]:
             text_height = value
         elif key == self.KEYS["TEXT_ROTATION"]:
             rotation = value
             # according to DXF spec: the last one wins
             direction_vector = [None, None, None]
         elif key == self.KEYS["TEXT_FONT"]:
             font_name = value
         elif key == self.KEYS["MTEXT_ALIGNMENT"]:
             alignment = value
         elif key == self.KEYS["TEXT_WIDTH_FINAL"]:
             width_final = value
         else:
             pass
         key, value = self._read_key_value()
     end_line = self.line_number
     # The last lines were not used - they are just the marker for the next
     # item.
     text = "".join(text_groups_start) + text_end
     if not key is None:
         self._push_on_stack(key, value)
     if None in ref_point:
         log.warn("DXFImporter: Incomplete MTEXT definition between line " \
                 + "%d and %d: missing location point" % \
                 (start_line, end_line))
     elif not text:
         log.warn("DXFImporter: Incomplete MTEXT definition between line " \
                 + "%d and %d: missing text" % (start_line, end_line))
     elif not text_height:
         log.warn("DXFImporter: Incomplete MTEXT definition between line " \
                 + "%d and %d: missing height" % (start_line, end_line))
     else:
         if self._color_as_height and (not color is None):
             # use the color code as the z coordinate
             ref_point[2] = float(color) / 255
         if self._fonts_cache:
             font = self._fonts_cache.get_font(font_name)
         else:
             font = None
         if not font:
             log.warn("DXFImporter: No fonts are available - skipping " + \
                     "MTEXT item between line %d and %d" % \
                     (start_line, end_line))
             return
         model = font.render(text)
         if (model.minx is None) or (model.miny is None) or \
                 (model.minz is None) or (model.minx == model.maxx) or \
                 (model.miny == model.maxy):
             log.warn("DXFImporter: Empty rendered MTEXT item between " + \
                     "line %d and %d" % (start_line, end_line))
             return
         model.scale(text_height / (model.maxy - model.miny),
                 callback=self.callback)
         # this setting seems to refer to a box - not the text width - ignore
         if False and width_final:
             scale_x = width_final / (model.maxx - model.minx)
             model.scale(scale_x, callback=self.callback)
         if rotation:
             matrix = pycam.Geometry.Matrix.get_rotation_matrix_axis_angle(
                     (0, 0, 1), rotation)
         elif not None in direction_vector:
             # Due to the parsing code above only "rotation" or
             # "direction_vector" is set at the same time.
             matrix = pycam.Geometry.Matrix.get_rotation_matrix_from_to(
                     (1, 0, 0), direction_vector)
         else:
             matrix = None
         if matrix:
             model.transform_by_matrix(matrix, callback=self.callback)
         # horizontal alignment
         if alignment % 3 == 1:
             offset_horiz = 0
         elif alignment % 3 == 2:
             offset_horiz = -(model.maxx - model.minx) / 2
         else:
             offset_horiz = -(model.maxx - model.minx)
         # vertical alignment
         if alignment <= 3:
             offset_vert = -(model.maxy - model.miny)
         elif alignment <= 6:
             offset_vert = -(model.maxy - model.miny) / 2
         else:
             offset_vert = 0
         # shift the text to its final destination
         shift_x = ref_point[0] - model.minx + offset_horiz
         shift_y = ref_point[1] - model.miny + offset_vert
         shift_z = ref_point[2] - model.minz
         model.shift(shift_x, shift_y, shift_z, callback=self.callback)
         for polygon in model.get_polygons():
             for line in polygon.get_lines():
                 self.lines.append(line)
コード例 #52
0
ファイル: Generator.py プロジェクト: CactusLibidineux/PyCAM
def _get_pathgenerator_instance(trimesh_models, contour_model, cutter,
        pathgenerator, pathprocessor, physics, milling_style):
    if pathgenerator != "EngraveCutter" and contour_model:
        return ("The only available toolpath strategy for 2D contour models " \
                + "is 'Engraving'.")
    if pathgenerator == "DropCutter":
        if pathprocessor == "ZigZagCutter":
            processor = PathAccumulator.PathAccumulator(zigzag=True)
        elif pathprocessor == "PathAccumulator":
            processor = PathAccumulator.PathAccumulator()
        else:
            return ("Invalid postprocessor (%s) for 'DropCutter': only " \
                    + "'ZigZagCutter' or 'PathAccumulator' are allowed") \
                    % str(pathprocessor)
        return DropCutter.DropCutter(cutter, trimesh_models, processor,
                physics=physics)
    elif pathgenerator == "PushCutter":
        if pathprocessor == "PathAccumulator":
            processor = PathAccumulator.PathAccumulator()
        elif pathprocessor == "SimpleCutter":
            processor = SimpleCutter.SimpleCutter()
        elif pathprocessor == "ZigZagCutter":
            processor = ZigZagCutter.ZigZagCutter()
        elif pathprocessor == "PolygonCutter":
            processor = PolygonCutter.PolygonCutter()
        elif pathprocessor == "ContourCutter":
            processor = ContourCutter.ContourCutter()
        else:
            return ("Invalid postprocessor (%s) for 'PushCutter' - it " + \
                    "should be one of these: %s") % \
                    (pathprocessor, PATH_POSTPROCESSORS)
        return PushCutter.PushCutter(cutter, trimesh_models, processor,
                physics=physics)
    elif pathgenerator == "EngraveCutter":
        clockwise = (milling_style == "climb")
        if pathprocessor == "SimpleCutter":
            processor = SimpleCutter.SimpleCutter()
        else:
            return ("Invalid postprocessor (%s) for 'EngraveCutter' - it " \
                    + "should be: SimpleCutter") % str(pathprocessor)
        if not contour_model:
            return "The 'Engraving' toolpath strategy requires a 2D contour " \
                    + "model (e.g. from a DXF or SVG file)."
        return EngraveCutter.EngraveCutter(cutter, trimesh_models,
                contour_model, processor, clockwise=clockwise, physics=physics)
    elif pathgenerator == "ContourFollow":
        reverse = (milling_style == "conventional")
        if pathprocessor == "SimpleCutter":
            processor = SimpleCutter.SimpleCutter(reverse=reverse)
        else:
            return ("Invalid postprocessor (%s) for 'ContourFollow' - it " \
                    + "should be: SimpleCutter") % str(pathprocessor)
        if not isinstance(cutter, CylindricalCutter):
            log.warn("The ContourFollow strategy only works reliably with " + \
                    "the cylindrical cutter shape. Maybe you should use " + \
                    "the alternative ContourPolygon strategy instead.")
        return ContourFollow.ContourFollow(cutter, trimesh_models, processor,
                physics=physics)
    elif pathgenerator == "Contour2dCutter": #JULIEN
        return Contour2dCutter.Contour2dCutter(cutter, trimesh_models, \
                Contour2dFlooder.Contour2dFlooder())
    else:
        return "Invalid path generator (%s): not one of %s" \
                % (pathgenerator, PATH_GENERATORS)
コード例 #53
0
ファイル: CXFImporter.py プロジェクト: chriskyfung/MakerDroid
                        raise _CXFParseError("Failed to read item coordinates" \
                                + " in line %d" % feeder.get_index())
                self.letters[character] = char_definition
            else:
                # unknown line format
                raise _CXFParseError("Failed to parse unknown content in " \
                        + "line %d" % feeder.get_index())


def import_font(filename, callback=None):
    try:
        infile = pycam.Utils.URIHandler(filename).open()
    except IOError, err_msg:
        log.error("CXFImporter: Failed to read file (%s): %s" \
                % (filename, err_msg))
        return None
    try:
        parsed_font = CXFParser(infile, callback=callback)
    except _CXFParseError, err_msg:
        log.warn("CFXImporter: Skipped font defintion file '%s'. Reason: %s." \
                % (filename, err_msg))
        return None
    charset = Charset(**parsed_font.meta)
    for key, value in parsed_font.letters.iteritems():
        charset.add_character(key, value)
    log.info("CXFImporter: Imported CXF font from '%s': %d letters" \
            % (filename, len(parsed_font.letters)))
    infile.close()
    return charset

コード例 #54
0
ファイル: DXFImporter.py プロジェクト: I--Fox--I/pycam
        try:
            infile = pycam.Utils.URIHandler(filename).open()
        except IOError, err_msg:
            log.error("DXFImporter: Failed to read file (%s): %s" \
                    % (filename, err_msg))
            return None

    result = DXFParser(infile, color_as_height=color_as_height,
            fonts_cache=fonts_cache, callback=callback)

    model_data = result.get_model()
    lines = model_data["lines"]
    triangles = model_data["triangles"]

    if callback and callback():
        log.warn("DXFImporter: load model operation was cancelled")
        return None

    # 3D models are preferred over 2D models
    if triangles:
        if lines:
            log.warn("DXFImporter: Ignoring 2D elements in DXF file: " + \
                    "%d lines" % len(lines))
        model = pycam.Geometry.Model.Model()
        for index, triangle in enumerate(triangles):
            model.append(triangle)
            # keep the GUI smooth
            if callback and (index % 50 == 0):
                callback()
        log.info("DXFImporter: Imported DXF model (3D): %d triangles" % \
                len(model.triangles()))