Example #1
0
 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
Example #2
0
def detect_file_type(filename, quiet=False):
    import pycam.Importers.DXFImporter
    import pycam.Importers.PSImporter
    import pycam.Importers.STLImporter
    import pycam.Importers.SVGImporter
    # also accept URI input
    uri = pycam.Utils.URIHandler(filename)
    filename = uri.get_path()
    failure = (None, None)
    # check all listed importers
    # TODO: this should be done by evaluating the header of the file
    if filename.lower().endswith(".stl"):
        return ("stl", pycam.Importers.STLImporter.ImportModel)
    elif filename.lower().endswith(".dxf"):
        return ("dxf", pycam.Importers.DXFImporter.import_model)
    elif filename.lower().endswith(".svg"):
        return ("svg", pycam.Importers.SVGImporter.import_model)
    elif filename.lower().endswith(".eps") \
            or filename.lower().endswith(".ps"):
        return ("ps", pycam.Importers.PSImporter.import_model)
    else:
        if not quiet:
            log.error(
                "Importers: Failed to detect the model type of '%s'. Is the file extension "
                "(stl/dxf/svg/eps/ps) correct?", filename)
        return failure
Example #3
0
 def combine_rectangles(r1, r2):
     shared_vertices = []
     shared_vertices2 = []
     for point in r1.get_points():
         for point2 in r2.get_points():
             if point == point2:
                 shared_vertices.append(point)
                 shared_vertices2.append(point2)
                 break
     if len(shared_vertices) != 2:
         return None
     # check if the two points form an edge (and not a diagonal line)
     corners = []
     for rectangle, vertices in ((r1, shared_vertices),
             (r2, shared_vertices2)):
         # turn the tuple into a list (".index" was introduced in Python 2.6)
         i1 = list(rectangle.get_points()).index(vertices[0])
         i2 = list(rectangle.get_points()).index(vertices[1])
         if i1 + i2 % 2 == 0:
             # shared vertices are at opposite corners
             return None
         # collect all non-shared vertices
         corners.extend([p for p in rectangle.get_points()
                 if not p in vertices])
     if len(corners) != 4:
         log.error("Unexpected corner count: %s / %s / %s" % (r1, r2, corners))
         return None
     try:
         return Rectangle(corners[0], corners[1], corners[2], corners[3],
                 normal=r1.normal)
     except ValueError:
         log.error("No valid rectangle found: %s" % corners)
         return None
Example #4
0
def detect_file_type(filename, quiet=False):
    # also accept URI input
    uri = pycam.Utils.URIHandler(filename)
    filename = uri.get_path()
    failure = (None, None)
    # check all listed importers
    # TODO: this should be done by evaluating the header of the file
    if filename.lower().endswith(".stl"):
        return ("stl", pycam.Importers.STLImporter.ImportModel)
    elif filename.lower().endswith(".dxf"):
        return ("dxf", pycam.Importers.DXFImporter.import_model)
    elif filename.lower().endswith(".svg"):
        return ("svg", pycam.Importers.SVGImporter.import_model)
    elif filename.lower().endswith(".eps") or filename.lower().endswith(".ps"):
        return ("ps", pycam.Importers.PSImporter.import_model)
    else:
        if not quiet:
            log.error(
                (
                    "Importers: Failed to detect the model type of '%s'. "
                    + "Is the file extension (stl/dxf/svg/eps/ps) correct?"
                )
                % filename
            )
        return failure
Example #5
0
 def check_header(self):
     # TODO: this function is not used?
     # we expect "0" in the first line and "SECTION" in the second one
     key, value = self._read_key_value()
     if (key != self.KEYS["MARKER"]) or (value and (value != "SECTION")):
         log.error("DXFImporter: DXF file header not recognized")
         return None
Example #6
0
 def handle_data_drop(self, widget, drag_context, x, y, selection_data, info,
         timestamp):
     if info != 0:
         uris = [str(selection_data.data)]
     elif pycam.Utils.get_platform() == pycam.Utils.PLATFORM_WINDOWS:
         uris = selection_data.data.splitlines()
     else:
         uris = selection_data.get_uris()
     if not uris:
         # empty selection
         return True
     for uri in uris:
         if not uri or (uri == chr(0)):
             continue
         uri = pycam.Utils.URIHandler(uri)
         file_type, importer = pycam.Importers.detect_file_type(uri,
                 quiet=True)
         if importer:
             # looks like the file can be loaded
             if self.load_model_file(filename=uri):
                 return True
     if len(uris) > 1:
         log.error("Failed to open any of the given models: %s" % \
                 str(uris))
     else:
         log.error("Failed to open the model: %s" % str(uris[0]))
     return False
Example #7
0
 def load_model_file(self, widget=None, filename=None, store_filename=True):
     if callable(filename):
         filename = filename()
     if not filename:
         filename = self.settings.get("get_filename_func")(
             "Loading model ...", mode_load=True, type_filter=FILTER_MODEL)
     if filename:
         file_type, importer = pycam.Importers.detect_file_type(filename)
         if file_type and callable(importer):
             progress = self.settings.get("progress")
             progress.update(text="Loading model ...")
             # "cancel" is not allowed
             progress.disable_cancel()
             if self.load_model(
                     importer(filename,
                              program_locations=get_all_program_locations(
                                  self.settings),
                              unit=self.settings.get("unit"),
                              fonts_cache=self.settings.get("fonts"),
                              callback=progress.update)):
                 if store_filename:
                     self.set_model_filename(filename)
                 self.add_to_recent_file_list(filename)
                 result = True
             else:
                 result = False
             progress.finish()
             return result
         else:
             log.error("Failed to detect filetype!")
             return False
Example #8
0
 def save_task_settings_file(self, widget=None, filename=None):
     if callable(filename):
         filename = filename()
     if not isinstance(filename, (basestring, pycam.Utils.URIHandler)):
         # we open a dialog
         filename = self.settings.get("get_filename_func")(
             "Save settings to ...",
             mode_load=False,
             type_filter=FILTER_CONFIG,
             filename_templates=(self.last_task_settings_uri,
                                 self.last_model_uri))
         if filename:
             self.last_task_settings_uri = pycam.Utils.URIHandler(filename)
     # no filename given -> exit
     if not filename:
         return
     settings = self.settings.dump_state()
     try:
         out_file = open(filename, "w")
         out_file.write(settings)
         out_file.close()
         log.info("Task settings written to %s" % filename)
         self.add_to_recent_file_list(filename)
     except IOError:
         log.error("Failed to save settings file")
Example #9
0
 def transform_by_matrix(self, matrix, transformed_list=None, callback=None):
     if transformed_list is None:
         transformed_list = []
     # Prevent any kind of loops or double transformations (e.g. Points in
     # multiple containers (Line, Triangle, ...).
     # Use the 'id' builtin to prevent expensive object comparions.
     for item in self.next():
         if isinstance(item, TransformableContainer):
             item.transform_by_matrix(matrix, transformed_list,callback=callback)
         elif not id(item) in transformed_list:
             # non-TransformableContainer do not care to update the
             # 'transformed_list'. Thus we need to do it.
             #transformed_list.append(id(item))
             # Don't transmit the 'transformed_list' if the object is
             # not a TransformableContainer. It is not necessary and it
             # is hard to understand on the lowest level (e.g. Point).
             if isinstance(item, str):
                 theval = getattr(self, item)
                 if isinstance(theval, tuple):
                     setattr(self, item, ptransform_by_matrix(theval, matrix))
                 elif isinstance(theval, list):
                     setattr(self, item, [ptransform_by_matrix(x, matrix) for x in theval])
             elif isinstance(item, tuple):
                 log.error("ERROR!! A tuple (Point, Vector) made it into base transform_by_matrix without a back reference. Point/Vector remains unchanged.")
             else:
                 item.transform_by_matrix(matrix, callback=callback)
         # run the callback - e.g. for a progress counter
         if callback and callback():
             # user requesteded abort
             break
     self.reset_cache()
Example #10
0
 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
Example #11
0
def ImportModel(filename, use_kdtree=True, callback=None, **kwargs):
    global vertices, edges, kdtree
    vertices = 0
    edges = 0
    kdtree = None

    normal_conflict_warning_seen = False

    if hasattr(filename, "read"):
        # make sure that the input stream can seek and has ".len"
        f = StringIO.StringIO(filename.read())
        # useful for later error messages
        filename = "input stream"
    else:
        try:
            url_file = pycam.Utils.URIHandler(filename).open()
            # urllib.urlopen objects do not support "seek" - so we need to read
            # the whole file at once. This is ugly - anyone with a better idea?
            f = StringIO.StringIO(url_file.read())
            # TODO: the above ".read" may be incomplete - this is ugly
            # see http://patrakov.blogspot.com/2011/03/case-of-non-raised-exception.html
            # and http://stackoverflow.com/questions/1824069/urllib2-not-retrieving-entire-http-response
            url_file.close()
        except IOError, err_msg:
            log.error("STLImporter: Failed to read file (%s): %s" \
                    % (filename, err_msg))
            return None
Example #12
0
 def load_model_file(self, widget=None, filename=None, store_filename=True):
     if callable(filename):
         filename = filename()
     if not filename:
         filename = self.settings.get("get_filename_func")("Loading model ...",
                 mode_load=True, type_filter=FILTER_MODEL)
     if filename:
         file_type, importer = pycam.Importers.detect_file_type(filename)
         if file_type and callable(importer):
             progress = self.settings.get("progress")
             progress.update(text="Loading model ...")
             # "cancel" is not allowed
             progress.disable_cancel()
             if self.load_model(importer(filename,
                     program_locations=get_all_program_locations(self.settings),
                     unit=self.settings.get("unit"),
                     fonts_cache=self.settings.get("fonts"),
                     callback=progress.update)):
                 if store_filename:
                     self.set_model_filename(filename)
                 self.add_to_recent_file_list(filename)
                 result = True
             else:
                 result = False
             progress.finish()
             return result
         else:
             log.error("Failed to detect filetype!")
             return False
Example #13
0
 def check_header(self):
     # TODO: this function is not used?
     # we expect "0" in the first line and "SECTION" in the second one
     key, value = self._read_key_value()
     if (key != self.KEYS["MARKER"]) or (value and (value != "SECTION")):
         log.error("DXFImporter: DXF file header not recognized")
         return None
Example #14
0
 def combine_rectangles(r1, r2):
     shared_vertices = []
     shared_vertices2 = []
     for point in r1.get_points():
         for point2 in r2.get_points():
             if point == point2:
                 shared_vertices.append(point)
                 shared_vertices2.append(point2)
                 break
     if len(shared_vertices) != 2:
         return None
     # check if the two points form an edge (and not a diagonal line)
     corners = []
     for rectangle, vertices in ((r1, shared_vertices), (r2, shared_vertices2)):
         # turn the tuple into a list (".index" was introduced in Python 2.6)
         i1 = list(rectangle.get_points()).index(vertices[0])
         i2 = list(rectangle.get_points()).index(vertices[1])
         if i1 + i2 % 2 == 0:
             # shared vertices are at opposite corners
             return None
         # collect all non-shared vertices
         corners.extend([p for p in rectangle.get_points() if p not in vertices])
     if len(corners) != 4:
         log.error("Unexpected corner count: %s / %s / %s", r1, r2, corners)
         return None
     try:
         return Rectangle(corners[0], corners[1], corners[2], corners[3], normal=r1.normal)
     except ValueError:
         log.error("No valid rectangle found: %s", corners)
         return None
Example #15
0
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
Example #16
0
 def load_workspace_from_file(self,
                              filename,
                              remember_uri=True,
                              default_content=None):
     if remember_uri:
         self.last_workspace_uri = pycam.Utils.URIHandler(filename)
         self.settings.get("set_last_filename")(filename)
     log.info("Loading workspace from file: %s", filename)
     try:
         with open_file_context(filename, "r", True) as in_file:
             content = in_file.read()
     except OSError as exc:
         if default_content:
             content = default_content
         else:
             log.error("Failed to read workspace file (%s): %s", filename,
                       exc)
             return False
     try:
         return self.load_workspace_from_description(content)
     except PycamBaseException as exc:
         log.warning(
             "Failed to load workspace description from file (%s): %s",
             filename, exc)
         if default_content:
             log.info("Falling back to default workspace due to load error")
             self.load_workspace_from_description(default_content)
         return False
Example #17
0
 def handle_data_drop(self, widget, drag_context, x, y, selection_data,
                      info, timestamp):
     if info != 0:
         uris = [str(selection_data.data)]
     elif pycam.Utils.get_platform() == pycam.Utils.OSPlatform.WINDOWS:
         uris = selection_data.data.splitlines()
     else:
         uris = selection_data.get_uris()
     if not uris:
         # empty selection
         return True
     for uri in uris:
         if not uri or (uri == chr(0)):
             continue
         detected_filetype = pycam.Importers.detect_file_type(uri,
                                                              quiet=True)
         if detected_filetype:
             # looks like the file can be loaded
             if self.load_model_file(filename=detected_filetype.uri):
                 return True
     if len(uris) > 1:
         log.error("Failed to open any of the given models: %s", str(uris))
     else:
         log.error("Failed to open the model: %s", str(uris[0]))
     return False
Example #18
0
def execute(parser, args, pycam):
    # try to change the process name
    pycam.Utils.setproctitle("pycam")

    if args.trace:
        log.setLevel(logging.DEBUG // 2)
    elif args.debug:
        log.setLevel(logging.DEBUG)
    elif args.quiet:
        log.setLevel(logging.WARNING)
        # disable the progress bar
        args.progress = "none"
        # silence all warnings
        warnings.filterwarnings("ignore")
    else:
        log.setLevel(logging.INFO)

    # check if server-auth-key is given -> this is mandatory for server mode
    if (args.enable_server or args.start_server) and not args.server_authkey:
        parser.error(
            "You need to supply a shared secret for server mode. This is supposed to prevent you "
            "from exposing your host to remote access without authentication.\nPlease add the "
            "'--server-auth-key' argument followed by a shared secret password."
        )
        return EXIT_CODES["server_without_password"]

    # initialize multiprocessing
    try:
        if args.server_authkey is None:
            server_auth_key = None
        else:
            server_auth_key = args.server_authkey.encode("utf-8")
        if args.start_server:
            pycam.Utils.threading.init_threading(
                args.parallel_processes,
                remote=args.remote_server,
                run_server=True,
                server_credentials=server_auth_key)
            pycam.Utils.threading.cleanup()
            return EXIT_CODES["ok"]
        else:
            pycam.Utils.threading.init_threading(
                args.parallel_processes,
                enable_server=args.enable_server,
                remote=args.remote_server,
                server_credentials=server_auth_key)
    except socket.error as err_msg:
        log.error("Failed to connect to remote server: %s", err_msg)
        return EXIT_CODES["connection_error"]
    except AuthenticationError as err_msg:
        log.error("The remote server rejected your authentication key: %s",
                  err_msg)
        return EXIT_CODES["connection_error"]

    try:
        show_gui()
    except InitializationError as exc:
        EmergencyDialog("PyCAM startup failure", str(exc))
        return EXIT_CODES["requirements"]
Example #19
0
def requirements_details_gtk():
    result = {}
    try:
        import_gtk_carefully()
        result["gtk"] = True
    except ImportError, err_msg:
        log.error("Failed to import GTK: %s" % str(err_msg))
        result["gtk"] = False
Example #20
0
 def load_from_string(self, config_text):
     input_text = StringIO.StringIO(config_text)
     try:
         self.reset(input_text)
     except ConfigParser.ParsingError, err_msg:
         log.error("Settings: Failed to parse config data: %s" % \
                 str(err_msg))
         return False
Example #21
0
 def register_ui_section(self, section, add_action, clear_action):
     if section not in self.ui_sections:
         self.ui_sections[section] = UISection(None, None, [])
     else:
         log.error("Trying to register a ui section twice: %s", section)
     self.ui_sections[section] = UISection(
         add_action, clear_action, self.ui_sections[section].widgets)
     self._rebuild_ui_section(section)
Example #22
0
 def load_from_string(self, config_text):
     input_text = StringIO.StringIO(config_text)
     try:
         self.reset(input_text)
     except ConfigParser.ParsingError, err_msg:
         log.error("Settings: Failed to parse config data: %s" % \
                 str(err_msg))
         return False
Example #23
0
 def load_file(self, filename):
     uri = pycam.Utils.URIHandler(filename)
     try:
         handle = uri.open()
         content = handle.read()
     except IOError, err_msg:
         log.error("Settings: Failed to read config file '%s': %s" \
                 % (uri, err_msg))
         return False
Example #24
0
 def load_file(self, filename):
     uri = pycam.Utils.URIHandler(filename)
     try:
         handle = uri.open()
         content = handle.read()
     except IOError, err_msg:
         log.error("Settings: Failed to read config file '%s': %s" \
                 % (uri, err_msg))
         return False
Example #25
0
 def _locate_external_program(self, widget=None, key=None):
     # the button was just activated
     location = get_external_program_location(key)
     if not location:
         log.error("Failed to locate the external program '%s'. Please install the program and "
                   "try again.%sOr maybe you need to specify the location manually.",
                   key, os.linesep)
     else:
         # store the new setting
         self.settings.set("external_program_%s" % key, location)
Example #26
0
 def _locate_external_program(self, widget=None, key=None):
     # the button was just activated
     location = get_external_program_location(key)
     if not location:
         log.error("Failed to locate the external program '%s'. " % key \
                 + "Please install the program and try again." \
                 + os.linesep \
                 + "Or maybe you need to specify the location manually.")
     else:
         # store the new setting
         self.settings.set("external_program_%s" % key, location)
Example #27
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, err_msg:
            log.error("DXFImporter: Failed to read file (%s): %s" \
                    % (filename, err_msg))
            return None
Example #28
0
def get_data_file_location(filename, silent=False):
    for base_dir in DATA_BASE_DIRS:
        test_path = os.path.join(base_dir, filename)
        if os.path.exists(test_path):
            return test_path
    if not silent:
        log.error(
            "Failed to locate a resource file (%s) in %s! "
            "You can extend the search path by setting the environment variable '%s'.",
            filename, DATA_BASE_DIRS, str(DATA_DIR_ENVIRON_KEY))
    return None
Example #29
0
 def write_to_file(self, filename, tools=None, processes=None, bounds=None,
         tasks=None):
     uri = pycam.Utils.URIHandler(filename)
     text = self.get_config_text(tools, processes, bounds, tasks)
     try:
         handle = open(uri.get_local_path(), "w")
         handle.write(text)
         handle.close()
     except IOError, err_msg:
         log.error("Settings: Failed to write configuration to file " \
                 + "(%s): %s" % (filename, err_msg))
         return False
Example #30
0
 def save_workspace_to_file(self, filename, remember_uri=True):
     from pycam.Flow.parser import dump_yaml
     if remember_uri:
         self.last_workspace_uri = pycam.Utils.URIHandler(filename)
         self.settings.emit_event("notify-file-opened", filename)
     log.info("Storing workspace in file: %s", filename)
     try:
         with open_file_context(filename, "w", True) as out_file:
             dump_yaml(target=out_file)
     except OSError as exc:
         log.error("Failed to store workspace in file '%s': %s", filename,
                   exc)
Example #31
0
 def gui_activity_guard_wrapper(self, *args, **kwargs):
     if self.gui_is_active:
         return
     self.gui_is_active = True
     try:
         result = func(self, *args, **kwargs)
     except Exception:
         # Catch possible exceptions (except system-exit ones) and
         # report them.
         log.error(pycam.Utils.get_exception_report())
         result = None
     self.gui_is_active = False
     return result
Example #32
0
def get_output_handler(destination):
    if destination == "-":
        handler = sys.stdout
        closer = lambda: None
    else:
        # support paths with a tilde (~)
        destination = os.path.expanduser(destination)
        try:
            handler = open(destination, "w")
        except IOError, err_msg:
            log.error("Failed to open output file (%s) for writing: %s" \
                    % (destination, err_msg))
            return None, None
        closer = handler.close
Example #33
0
def get_data_file_location(filename, silent=False, priority_directories=None):
    if priority_directories is None:
        scan_dirs = DATA_BASE_DIRS
    else:
        scan_dirs = tuple(priority_directories) + tuple(DATA_BASE_DIRS)
    for base_dir in scan_dirs:
        test_path = os.path.join(base_dir, filename)
        if os.path.exists(test_path):
            return test_path
    if not silent:
        log.error("Failed to locate a resource file (%s) in %s! "
                  "You can extend the search path by setting the environment variable '%s'.",
                  filename, DATA_BASE_DIRS, str(DATA_DIR_ENVIRON_KEY))
    return None
Example #34
0
def get_output_handler(destination):
    if destination == "-":
        handler = sys.stdout
        closer = lambda: None
    else:
        # support paths with a tilde (~)
        destination = os.path.expanduser(destination)
        try:
            handler = open(destination, "w")
        except IOError, err_msg:
            log.error("Failed to open output file (%s) for writing: %s" \
                    % (destination, err_msg))
            return None, None
        closer = handler.close
Example #35
0
def get_data_file_location(filename, silent=False):
    for base_dir in DATA_BASE_DIRS:
        test_path = os.path.join(base_dir, filename)
        if os.path.exists(test_path):
            return test_path
    else:
        if not silent:
            lines = []
            lines.append("Failed to locate a resource file (%s) in %s!" \
                    % (filename, DATA_BASE_DIRS))
            lines.append("You can extend the search path by setting the " \
                    + "environment variable '%s'." % str(DATA_DIR_ENVIRON_KEY))
            log.error(os.linesep.join(lines))
        return None
Example #36
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, err_msg:
            log.error("DXFImporter: Failed to read file (%s): %s" \
                    % (filename, err_msg))
            return None
Example #37
0
def get_data_file_location(filename, silent=False):
    for base_dir in DATA_BASE_DIRS:
        test_path = os.path.join(base_dir, filename)
        if os.path.exists(test_path):
            return test_path
    else:
        if not silent:
            lines = []
            lines.append("Failed to locate a resource file (%s) in %s!" % (filename, DATA_BASE_DIRS))
            lines.append(
                "You can extend the search path by setting the "
                + "environment variable '%s'." % str(DATA_DIR_ENVIRON_KEY)
            )
            log.error(os.linesep.join(lines))
        return None
Example #38
0
 def load_file(self, filename):
     uri = pycam.Utils.URIHandler(filename)
     try:
         handle = uri.open()
         content = handle.read()
     except IOError as err_msg:
         log.error("Settings: Failed to read config file '%s': %s", uri,
                   err_msg)
         return False
     try:
         self.reset(content)
     except ConfigParser.ParsingError as err_msg:
         log.error("Settings: Failed to parse config file '%s': %s", uri,
                   err_msg)
         return False
     return True
Example #39
0
 def gui_activity_guard_wrapper(self, *args, **kwargs):
     if self.gui_is_active:
         return
     self.gui_is_active = True
     try:
         result = func(self, *args, **kwargs)
     except Exception:
         # Catch possible exceptions (except system-exit ones) and
         # report them.
         log.error(pycam.Utils.get_exception_report())
         result = None
     self.gui_is_active = False
     while self._batch_queue:
         batch_func, batch_args, batch_kwargs = self._batch_queue[0]
         del self._batch_queue[0]
         batch_func(*batch_args, **batch_kwargs)
     return result
Example #40
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
Example #41
0
 def transform_by_matrix(self,
                         matrix,
                         transformed_list=None,
                         callback=None):
     if transformed_list is None:
         transformed_list = []
     # Prevent any kind of loops or double transformations (e.g. Points in
     # multiple containers (Line, Triangle, ...).
     # Use the 'id' builtin to prevent expensive object comparions.
     for item in self.next():
         if isinstance(item, TransformableContainer):
             item.transform_by_matrix(matrix,
                                      transformed_list,
                                      callback=callback)
         elif not id(item) in transformed_list:
             # non-TransformableContainer do not care to update the
             # 'transformed_list'. Thus we need to do it.
             #transformed_list.append(id(item))
             # Don't transmit the 'transformed_list' if the object is
             # not a TransformableContainer. It is not necessary and it
             # is hard to understand on the lowest level (e.g. Point).
             if isinstance(item, str):
                 theval = getattr(self, item)
                 if isinstance(theval, tuple):
                     setattr(self, item,
                             ptransform_by_matrix(theval, matrix))
                 elif isinstance(theval, list):
                     setattr(
                         self, item,
                         [ptransform_by_matrix(x, matrix) for x in theval])
             elif isinstance(item, tuple):
                 log.error(
                     "ERROR!! A tuple (Point, Vector) made it into base transform_by_matrix without a back reference. Point/Vector remains unchanged."
                 )
             else:
                 item.transform_by_matrix(matrix, callback=callback)
         # run the callback - e.g. for a progress counter
         if callback and callback():
             # user requesteded abort
             break
     self.reset_cache()
Example #42
0
 def save_task_settings_file(self, widget=None, filename=None):
     if callable(filename):
         filename = filename()
     if not isinstance(filename, (basestring, pycam.Utils.URIHandler)):
         # we open a dialog
         filename = self.settings.get("get_filename_func")("Save settings to ...",
                 mode_load=False, type_filter=FILTER_CONFIG,
                 filename_templates=(self.last_task_settings_uri, self.last_model_uri))
         if filename:
             self.last_task_settings_uri = pycam.Utils.URIHandler(filename)
     # no filename given -> exit
     if not filename:
         return
     settings = self.settings.dump_state()
     try:
         out_file = open(filename, "w")
         out_file.write(settings)
         out_file.close()
         log.info("Task settings written to %s" % filename)
         self.add_to_recent_file_list(filename)
     except IOError:
         log.error("Failed to save settings file")
Example #43
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)
Example #44
0
def ImportModel(filename, use_kdtree=True, callback=None, **kwargs):
    global vertices, edges, kdtree
    vertices = 0
    edges = 0
    kdtree = None

    normal_conflict_warning_seen = False

    if hasattr(filename, "read"):
        f = filename
        # useful for later error messages
        filename = "input stream"
    else:
        try:
            url_file = pycam.Utils.URIHandler(filename).open()
            # urllib.urlopen objects do not support "seek" - so we need to read
            # the whole file at once. This is ugly - anyone with a better idea?
            f = StringIO.StringIO(url_file.read())
            url_file.close()
        except IOError, err_msg:
            log.error("STLImporter: Failed to read file (%s): %s" \
                    % (filename, err_msg))
            return None
Example #45
0
def ImportModel(filename, use_kdtree=True, callback=None, **kwargs):
    global vertices, edges, kdtree
    vertices = 0
    edges = 0
    kdtree = None

    normal_conflict_warning_seen = False

    if hasattr(filename, "read"):
        f = filename
        # useful for later error messages
        filename = "input stream"
    else:
        try:
            url_file = pycam.Utils.URIHandler(filename).open()
            # urllib.urlopen objects do not support "seek" - so we need to read
            # the whole file at once. This is ugly - anyone with a better idea?
            f = StringIO.StringIO(url_file.read())
            url_file.close()
        except IOError, err_msg:
            log.error("STLImporter: Failed to read file (%s): %s" \
                    % (filename, err_msg))
            return None
Example #46
0
def execute(parser, opts, args, pycam):
    # try to change the process name
    pycam.Utils.setproctitle("pycam")

    if len(args) > 0:
        inputfile = pycam.Utils.URIHandler(args[0])
    else:
        inputfile = None

    if opts.debug:
        log.setLevel(logging.DEBUG)
    elif opts.quiet:
        log.setLevel(logging.WARNING)
        # disable the progress bar
        opts.progress = "none"
        # silence all warnings
        warnings.filterwarnings("ignore")
    else:
        # silence gtk warnings
        try:
            import gtk
            warnings.filterwarnings("ignore", category=gtk.Warning)
        except ImportError:
            pass

    # show version and exit
    if opts.show_version:
        if opts.quiet:
            # print only the bare version number
            print VERSION
        else:
            text = '''PyCAM %s
Copyright (C) 2008-2010 Lode Leroy
Copyright (C) 2010-2011 Lars Kruse

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.''' % VERSION
            print text
        return EXIT_CODES["ok"]

    if not opts.disable_psyco:
        try:
            import psyco
            psyco.full()
            log.info("Psyco enabled")
        except ImportError:
            log.info("Psyco is not available (performance will probably " \
                    + "suffer slightly)")
    else:
        log.info("Psyco was disabled via the commandline")

    # check if server-auth-key is given -> this is mandatory for server mode
    if (opts.enable_server or opts.start_server) and not opts.server_authkey:
        parser.error("You need to supply a shared secret for server mode. " \
                + "This is supposed to prevent you from exposing your host " \
                + "to remote access without authentication.\n" \
                + "Please add the '--server-auth-key' argument followed by " \
                + "a shared secret password.")
        return EXIT_CODES["server_without_password"]

    # initialize multiprocessing
    try:
        if opts.start_server:
            pycam.Utils.threading.init_threading(
                opts.parallel_processes,
                remote=opts.remote_server,
                run_server=True,
                server_credentials=opts.server_authkey)
            pycam.Utils.threading.cleanup()
            return EXIT_CODES["ok"]
        else:
            pycam.Utils.threading.init_threading(
                opts.parallel_processes,
                enable_server=opts.enable_server,
                remote=opts.remote_server,
                server_credentials=opts.server_authkey)
    except socket.error, err_msg:
        log.error("Failed to connect to remote server: %s" % err_msg)
        return EXIT_CODES["connection_error"]
Example #47
0
    try:
        if opts.start_server:
            pycam.Utils.threading.init_threading(opts.parallel_processes,
                    remote=opts.remote_server, run_server=True,
                    server_credentials=opts.server_authkey)
            pycam.Utils.threading.cleanup()
            return EXIT_CODES["ok"]
        else:
            pycam.Utils.threading.init_threading(opts.parallel_processes,
                    enable_server=opts.enable_server, remote=opts.remote_server,
                    server_credentials=opts.server_authkey)
    except socket.error, err_msg:
        log.error("Failed to connect to remote server: %s" % err_msg)
        return EXIT_CODES["connection_error"]
    except multiprocessing.AuthenticationError, err_msg:
        log.error("The remote server rejected your authentication key: %s" \
                % err_msg)
        return EXIT_CODES["connection_error"]

    # initialize the progress bar
    progress_styles = {"none": pycam.Gui.Console.ConsoleProgressBar.STYLE_NONE,
            "text": pycam.Gui.Console.ConsoleProgressBar.STYLE_TEXT,
            "bar": pycam.Gui.Console.ConsoleProgressBar.STYLE_BAR,
            "dot": pycam.Gui.Console.ConsoleProgressBar.STYLE_DOT,
    }
    progress_bar = pycam.Gui.Console.ConsoleProgressBar(sys.stdout,
            progress_styles[opts.progress])

    if opts.config_file:
        opts.config_file = os.path.expanduser(opts.config_file)

    if not opts.export_gcode and not opts.export_task_config:
Example #48
0
def execute(parser, opts, args, pycam):
    # try to change the process name
    pycam.Utils.setproctitle("pycam")

    if len(args) > 0:
        inputfile = pycam.Utils.URIHandler(args[0])
    else:
        inputfile = None

    if opts.debug:
        log.setLevel(logging.DEBUG)
    elif opts.quiet:
        log.setLevel(logging.WARNING)
        # disable the progress bar
        opts.progress = "none"
        # silence all warnings
        warnings.filterwarnings("ignore")
    else:
        # silence gtk warnings
        try:
            import gtk
            warnings.filterwarnings("ignore", category=gtk.Warning)
        except ImportError:
            pass

    # show version and exit
    if opts.show_version:
        if opts.quiet:
            # print only the bare version number
            print VERSION
        else:
            text = '''PyCAM %s
Copyright (C) 2008-2010 Lode Leroy
Copyright (C) 2010-2011 Lars Kruse

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.''' % VERSION
            print text
        return EXIT_CODES["ok"]

    if not opts.disable_psyco:
        try:
            import psyco
            psyco.full()
            log.info("Psyco enabled")
        except ImportError:
            log.info("Psyco is not available (performance will probably " \
                    + "suffer slightly)")
    else:
        log.info("Psyco was disabled via the commandline")

    # check if server-auth-key is given -> this is mandatory for server mode
    if (opts.enable_server or opts.start_server) and not opts.server_authkey:
        parser.error("You need to supply a shared secret for server mode. " \
                + "This is supposed to prevent you from exposing your host " \
                + "to remote access without authentication.\n" \
                + "Please add the '--server-auth-key' argument followed by " \
                + "a shared secret password.")
        return EXIT_CODES["server_without_password"]

    # initialize multiprocessing
    try:
        if opts.start_server:
            pycam.Utils.threading.init_threading(opts.parallel_processes,
                    remote=opts.remote_server, run_server=True,
                    server_credentials=opts.server_authkey)
            pycam.Utils.threading.cleanup()
            return EXIT_CODES["ok"]
        else:
            pycam.Utils.threading.init_threading(opts.parallel_processes,
                    enable_server=opts.enable_server, remote=opts.remote_server,
                    server_credentials=opts.server_authkey)
    except socket.error, err_msg:
        log.error("Failed to connect to remote server: %s" % err_msg)
        return EXIT_CODES["connection_error"]
Example #49
0
 def __init__(
     self, gui, settings, notify_destroy=None, accel_group=None, item_buttons=None, context_menu_actions=None
 ):
     # assume, that initialization will fail
     self.gui = gui
     self.window = self.gui.get_object("view3dwindow")
     if not accel_group is None:
         self.window.add_accel_group(accel_group)
     self.initialized = False
     self.busy = False
     self.settings = settings
     self.is_visible = False
     # check if the 3D view is available
     if GL_ENABLED:
         self.enabled = True
     else:
         log.error(
             "Failed to initialize the interactive 3D model view."
             + "\nPlease install 'python-gtkglext1' to enable it."
         )
         self.enabled = False
         return
     self.mouse = {
         "start_pos": None,
         "button": None,
         "event_timestamp": 0,
         "last_timestamp": 0,
         "pressed_pos": None,
         "pressed_timestamp": 0,
         "pressed_button": None,
     }
     self.notify_destroy_func = notify_destroy
     self.window.connect("delete-event", self.destroy)
     self.window.set_default_size(560, 400)
     self._position = self.gui.get_object("ProjectWindow").get_position()
     self._position = (self._position[0] + 100, self._position[1] + 100)
     self.container = self.gui.get_object("view3dbox")
     self.gui.get_object("Reset View").connect("clicked", self.rotate_view, VIEWS["reset"])
     self.gui.get_object("Left View").connect("clicked", self.rotate_view, VIEWS["left"])
     self.gui.get_object("Right View").connect("clicked", self.rotate_view, VIEWS["right"])
     self.gui.get_object("Front View").connect("clicked", self.rotate_view, VIEWS["front"])
     self.gui.get_object("Back View").connect("clicked", self.rotate_view, VIEWS["back"])
     self.gui.get_object("Top View").connect("clicked", self.rotate_view, VIEWS["top"])
     self.gui.get_object("Bottom View").connect("clicked", self.rotate_view, VIEWS["bottom"])
     # key binding
     self.window.connect("key-press-event", self.key_handler)
     # OpenGL stuff
     glconfig = gtk.gdkgl.Config(mode=gtk.gdkgl.MODE_RGBA | gtk.gdkgl.MODE_DEPTH | gtk.gdkgl.MODE_DOUBLE)
     self.area = gtk.gtkgl.DrawingArea(glconfig)
     # first run; might also be important when doing other fancy
     # gtk/gdk stuff
     self.area.connect_after("realize", self.paint)
     # called when a part of the screen is uncovered
     self.area.connect("expose-event", self.paint)
     # resize window
     self.area.connect("configure-event", self._resize_window)
     # catch mouse events
     self.area.set_events(
         gtk.gdk.MOUSE
         | gtk.gdk.POINTER_MOTION_HINT_MASK
         | gtk.gdk.BUTTON_PRESS_MASK
         | gtk.gdk.BUTTON_RELEASE_MASK
         | gtk.gdk.SCROLL_MASK
     )
     self.area.connect("button-press-event", self.mouse_press_handler)
     self.area.connect("motion-notify-event", self.mouse_handler)
     self.area.connect("button-release-event", self.context_menu_handler)
     self.area.connect("scroll-event", self.scroll_handler)
     self.container.pack_end(self.area)
     self.camera = Camera(self.settings, lambda: (self.area.allocation.width, self.area.allocation.height))
     # Color the dimension value according to the axes.
     # For "y" axis: 100% green is too bright on light background - we
     # reduce it a bit.
     for color, names in (
         (
             pango.AttrForeground(65535, 0, 0, 0, 100),
             ("model_dim_x_label", "model_dim_x", "ModelCornerXMax", "ModelCornerXMin", "ModelCornerXSpaces"),
         ),
         (
             pango.AttrForeground(0, 50000, 0, 0, 100),
             ("model_dim_y_label", "model_dim_y", "ModelCornerYMax", "ModelCornerYMin", "ModelCornerYSpaces"),
         ),
         (
             pango.AttrForeground(0, 0, 65535, 0, 100),
             ("model_dim_z_label", "model_dim_z", "ModelCornerZMax", "ModelCornerZMin", "ModelCornerZSpaces"),
         ),
     ):
         attributes = pango.AttrList()
         attributes.insert(color)
         for name in names:
             self.gui.get_object(name).set_attributes(attributes)
     # add the items buttons (for configuring visible items)
     if item_buttons:
         items_button_container = self.gui.get_object("ViewItems")
         for button in item_buttons:
             new_checkbox = gtk.ToggleToolButton()
             new_checkbox.set_label(button.get_label())
             new_checkbox.set_active(button.get_active())
             # Configure the two buttons (in "Preferences" and in the 3D view
             # widget) to toggle each other. This is required for a
             # consistent view of the setting.
             connect_button_handlers("toggled", button, new_checkbox)
             items_button_container.insert(new_checkbox, -1)
         items_button_container.show_all()
         # create the drop-down menu
         if context_menu_actions:
             action_group = gtk.ActionGroup("context")
             for action in context_menu_actions:
                 action_group.add_action(action)
             uimanager = gtk.UIManager()
             # The "pos" parameter is optional since gtk 2.12 - we can
             # remove it later.
             uimanager.insert_action_group(action_group, pos=-1)
             uimanager_template = '<ui><popup name="context">%s</popup></ui>'
             uimanager_item_template = """<menuitem action="%s" />"""
             uimanager_text = uimanager_template % "".join(
                 [uimanager_item_template % action.get_name() for action in context_menu_actions]
             )
             uimanager.add_ui_from_string(uimanager_text)
             self.context_menu = uimanager.get_widget("/context")
             self.context_menu.insert(gtk.SeparatorMenuItem(), 0)
         else:
             self.context_menu = gtk.Menu()
         for index, button in enumerate(item_buttons):
             new_item = gtk.CheckMenuItem(button.get_label())
             new_item.set_active(button.get_active())
             connect_button_handlers("toggled", button, new_item)
             self.context_menu.insert(new_item, index)
         self.context_menu.show_all()
     else:
         self.context_menu = None
     # show the window
     self.area.show()
     self.container.show()
     self.show()
Example #50
0
            # TODO: the above ".read" may be incomplete - this is ugly
            # see http://patrakov.blogspot.com/2011/03/case-of-non-raised-exception.html
            # and http://stackoverflow.com/questions/1824069/urllib2-not-retrieving-entire-http-response
            url_file.close()
        except IOError, err_msg:
            log.error("STLImporter: Failed to read file (%s): %s" \
                    % (filename, err_msg))
            return None
    # Read the first two lines of (potentially non-binary) input - they should
    # contain "solid" and "facet".
    header_lines = []
    while len(header_lines) < 2:
        line = f.readline(200)
        if len(line) == 0:
            # empty line (not even a line-feed) -> EOF
            log.error("STLImporter: No valid lines found in '%s'" % filename)
            return None
        # ignore comment lines
        # note: partial comments (starting within a line) are not handled
        if not line.startswith(";"):
            header_lines.append(line)
    header = "".join(header_lines)
    # read byte 80 to 83 - they contain the "numfacets" value in binary format
    f.seek(80)
    numfacets = unpack("<I", f.read(4))[0]
    binary = False
    log.debug("STL import info: %s / %s / %s / %s" % \
            (f.len, numfacets, header.find("solid"), header.find("facet")))

    if f.len == (84 + 50*numfacets):
        binary = True
Example #51
0
        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://sf.net/apps/mediawiki/pycam/?title=SupportedFormats"
        log.error('DXFImporter: No supported elements found in DXF file!\n' \
                + '<a href="%s">Read PyCAM\'s modelling hints.</a>' % link)
        return None