def test_generate_metainfo_filename(self): """ Tests that the generated metainfo filename is correct """ stats = PathInfo([], DummyOptions, "baseF") self.assertEqual(stats.metainfo_filename(), "baseF.psj")
def test_generate_svg_filename(self): """ Tests that the generated svg filename is correct """ stats = PathInfo([], DummyOptions, "baseF") self.assertEqual(stats.svg_filename(), "baseF.svg")
def test_return_outside_workpiece_when_path_right_outside(self): # pylint: disable=invalid-name """ Tests that when the path is outside border (right) is_path_inside_border returns false """ path = [(0, 0), (10, 10), (51, 20), (15, 14), (11, 17), (0, 0)] stats = PathInfo(path, DummyOptions(), "baseF") self.assertFalse(stats.is_path_inside_workpiece())
def test_estimate_working_time_to_0_if_path_single_point(self): # pylint: disable=invalid-name """ Tests that working time is 0 if path contains a single point """ ops = DummyOptions() ops.dim_x = 12 ops.dim_y = 34 stats = PathInfo([(1, 1)], ops, "baseF") self.assertEqual(stats.working_time_min(), 0)
def test_estimate_working_time_to_0_if_path_is_missing(self): # pylint: disable=invalid-name """ Tests that working time if estimated to 0 is path is missing """ ops = DummyOptions() ops.dim_x = 12 ops.dim_y = 34 stats = PathInfo([], ops, "baseF") self.assertEqual(stats.working_time_min(), 0)
def test_return_inside_border_when_path_inside(self): # pylint: disable=invalid-name """ Tests that when the path is inside border is_path_inside_border returns true """ path = [(0, 0), (10, 10), (20, 20), (15, 14), (11, 17), (0, 0)] ops = DummyOptions() ops.dim_x = 20 ops.dim_y = 20 stats = PathInfo(path, ops, "baseF") self.assertTrue(stats.is_path_inside_workpiece())
def test_estimate_to_0_if_speed_is_0(self): # pylint: disable=invalid-name """ Tests that working time estimate is 0 if speed is 0 """ path = [(0, 0), (10, 0), (10, 10), (0, 10)] ops = DummyOptions() ops.dim_x = 12 ops.dim_y = 34 ops.speed = 0 stats = PathInfo(path, ops, "baseF") self.assertEqual(stats.working_time_min(), 0)
def test_estimate_working_time(self): """ Tests estimated working time for a path """ path = [(0, 0), (10, 0), (10, 10), (0, 10)] ops = DummyOptions() ops.dim_x = 12 ops.dim_y = 34 stats = PathInfo(path, ops, "baseF") self.assertEqual(stats.working_time_min(), int(math.ceil(30 / MM_PER_MIN)))
def test_generate_metainfo(self): """ Tests that meta-information is correctly generated """ path = [(0, 0), (10, 0), (10, 10), (0, 10)] ops = DummyOptions() ops.shapename = "uhuh" ops.dim_x = 12 ops.dim_y = 34 ops.speed = 15.0 ops.flatness = 0.3 ops.square = False ops.margin = 2.5 ops.machine_type = "P400" ops.draw_toolpath = False ops.auto_close_path = True stats = PathInfo(path, ops, "baseF") metainfo = stats.metainfo() self.assertEqual(metainfo["version"], 1) self.assertEqual(metainfo["name"], "uhuh") self.assertEqual(metainfo["generatedBy"], "2DPlugin") self.assertEqual(metainfo["gcodeFilename"], "baseF.gcode") self.assertEqual(metainfo["svgFilename"], "baseF.svg") self.assertEqual(metainfo["duration"], 120) self.assertLess( abs((datetime.strptime(metainfo["creationTime"], "%Y-%m-%dT%H:%M:%S.%f") - datetime.now()).total_seconds()), 1) self.assertEqual(metainfo["pointsInsideWorkpiece"], True) self.assertEqual(metainfo["speed"], 15.0) self.assertEqual(metainfo["flatness"], 0.3) self.assertEqual(metainfo["square"], False) self.assertEqual(metainfo["margin"], 2.5) self.assertEqual(metainfo["machineType"], "P400") self.assertEqual(metainfo["drawToolpath"], False) self.assertEqual(metainfo["autoClosePath"], True)
def test_return_inside_workpiece_for_empty_path(self): # pylint: disable=invalid-name """ Test that is_path_inside_workpiece returns true for empty paths """ stats = PathInfo([], DummyOptions(), "baseF") self.assertTrue(stats.is_path_inside_workpiece())
def effect(self): """ Main function """ # First of all generating the machine instance and checking piece dimensions fit machine = machine_factory(self.options.machine_type) if machine: valid_dimensions = machine.piece_dimensions_allowed( self.options.dim_x, self.options.dim_y) if not valid_dimensions: raise InvalidWorkpieceDimensions(machine.working_area_width(), machine.working_area_height()) # A function to convert to millimiters to_mm = lambda value: self.uutounit(value, 'mm') # A function to convert to user units. This must be used to write units in the svg to_uu = lambda value: self.unittouu(str(value) + "mm") # Draw the working area working_area_generator = WorkingAreaGenerator(to_uu, WORKING_AREA_ID) working_area_generator.set_size(self.options.dim_x, self.options.dim_y) working_area_generator.upsert(self.document.getroot()) if not self.options.ids: # print info and exit inkex.debug( _(("No path was seletect, only the working area was generated. Now draw a " "path inside the working area and select it to generate the g-code" ))) else: # Extracting paths in machine coordinates paths_extractor = PathsExtractor( self.selected.values(), to_mm, WORKING_AREA_ID, FlattenBezier(self.options.flatness), self.options.auto_close_path) paths_extractor.extract() # The border to use. This is None if no border is requested. If border is present, also # draws it border = None if self.options.square: border = Border(paths_extractor.paths(), self.options.margin) painter = BorderPainter(border) painter.paint(working_area_generator) # Joining paths. This will also check that all paths are closed paths_joiner = PathsJoiner(paths_extractor.paths(), CLOSE_DISTANCE) paths_joiner.unite() # Generate tool positions tool_path_generator = CuttingToolPathsGenerator( paths_joiner.union_path(), CLOSE_DISTANCE, border) tool_path_generator.generate() # The object drawing the tool path painter = ToolPathPainter(tool_path_generator.path()) # Draw tool path on original svg if requested if self.options.draw_toolpath: painter.paint(working_area_generator.get_element(), working_area_generator.get_factor(), "255,0,0") # Generating g-code gcode_generator = CuttingGCodeGenerator(tool_path_generator.path(), self.options.speed) gcode_generator.generate() # Computing information about path generic_filename = base_filename(self.options.shapename, self.gcode_file_path) info = PathInfo(tool_path_generator.path(), self.options, generic_filename) # Writing gcode to file write_file( os.path.join(self.gcode_file_path, info.gcode_filename()), lambda f: f.write(gcode_generator.gcode())) # Writing svg to file doc = generate_path_svg(painter) write_file(os.path.join(self.gcode_file_path, info.svg_filename()), lambda f: doc.write(f)) # Writing metainfo to file write_file( os.path.join(self.gcode_file_path, info.metainfo_filename()), lambda f: f.write(json.dumps(info.metainfo(), indent=2))) message = (_("The generate g-code has been saved to ") + info.gcode_filename() + _(". Estimated working time: ") + str(info.working_time_min()) + _(" minutes")) if not info.is_path_inside_workpiece(): message += _( ". WARNING: some points are outside the workpiece") inkex.debug(message)