diff --git a/ahb_cmd_new_step.py b/ahb_cmd_new_step.py index 59ffa3c..41a35a4 100644 --- a/ahb_cmd_new_step.py +++ b/ahb_cmd_new_step.py @@ -64,6 +64,7 @@ class AHB_New_Step: view = doc.addObject('TechDraw::DrawViewPart', 'View') view.Perspective = False view.addProperty("App::PropertyString", "Assembly_handbook_PreviousStepView", "Assembly_handbook") + view.addProperty("App::PropertyBool", "Assembly_handbook_RasterView", "Assembly_handbook") if prev_view is None: try: workbench.techDrawExtensions.setCurrentViewDirection(view) diff --git a/ahb_techdraw_extensions.py b/ahb_techdraw_extensions.py index fdebe50..373b957 100644 --- a/ahb_techdraw_extensions.py +++ b/ahb_techdraw_extensions.py @@ -94,113 +94,173 @@ class TechDrawExtensions: for view in to_repaint: #print("Repainting " + view.Name) + page = self.getViewPage(view) + view_cache = self.getViewCache(view) view_cache.reset() doc = view.Document - fast_rendering = False - #try: - # fast_rendering = view.Assembly_handbook_FastRendering - #except: - # pass - - if view.CoarseView: - fast_rendering = True - - selected_balloons = [] - for obj in Gui.Selection.getSelection(): - if obj.TypeId == 'TechDraw::DrawViewBalloon' and obj.SourceView == view and 'Assembly_handbook_Source' in obj.PropertiesList: - selected_balloons.append(obj) - - #view.clearGeomFormats() # for an unknown reason, this will crash freecad - - if not fast_rendering: - is_first_part = True - - parts_to_paint = [] + if not 'Assembly_handbook_RasterView' in view.PropertiesList: + view.addProperty("App::PropertyBool", "Assembly_handbook_RasterView", "Assembly_handbook") - # repaint parts that are highlighted by selection - if self.enable_selected_part_highlight: - for balloon in selected_balloons: - part = self.getBalloonSourcePart(balloon) - if part in view.XSource: + if view.Assembly_handbook_RasterView: + print("Rasterizing view " + view.Label + "...") + imageName = view.Label + "_raster" + image = doc.getObject(imageName) + if image is None: + image = doc.addObject('TechDraw::DrawViewImage', view.Label + "_raster") + + if not image in page.Views: + page.addView(image) + + new_views_list = page.Views + new_views_list.remove(image) + view_idx = new_views_list.index(view) + new_views_list.insert(view_idx, image) + page.Views = new_views_list + + image_file_name = doc.FileName.replace('.FCStd', '') + '_raster/' + view.Name + '.png' + self.rasterizeView(view, image_file_name) + image.ImageFile = image_file_name # TODO: see if it's possible to set a relative path + image.recompute() + else: + fast_rendering = False + #try: + # fast_rendering = view.Assembly_handbook_FastRendering + #except: + # pass + + if view.CoarseView: + fast_rendering = True + + selected_balloons = [] + for obj in Gui.Selection.getSelection(): + if obj.TypeId == 'TechDraw::DrawViewBalloon' and obj.SourceView == view and 'Assembly_handbook_Source' in obj.PropertiesList: + selected_balloons.append(obj) + + #view.clearGeomFormats() # for an unknown reason, this will crash freecad + + if not fast_rendering: + is_first_part = True + + parts_to_paint = [] + + # repaint parts that are highlighted by selection + if self.enable_selected_part_highlight: + for balloon in selected_balloons: + part = self.getBalloonSourcePart(balloon) + if part in view.XSource: + parts_to_paint.append(part) + + # repaint parts that are new in this step (thick line) + prev_view = None + if 'Assembly_handbook_PreviousStepView' in view.PropertiesList: + prev_view = doc.getObject(view.Assembly_handbook_PreviousStepView) + for part in view.XSource: + if (prev_view is None or part not in prev_view.XSource) and part not in parts_to_paint: parts_to_paint.append(part) - - # repaint parts that are new in this step (thick line) - prev_view = None - if 'Assembly_handbook_PreviousStepView' in view.PropertiesList: - prev_view = doc.getObject(view.Assembly_handbook_PreviousStepView) - for part in view.XSource: - if (prev_view is None or part not in prev_view.XSource) and part not in parts_to_paint: - parts_to_paint.append(part) - - # make sure the list is not empty, so that we reset all lines - if len(parts_to_paint) == 0: - parts_to_paint.append(None) - for part in parts_to_paint: - default_line_thickness = 0.05 - line_thickness = default_line_thickness - - default_color = (0.0, 0.0, 0.0) if fast_rendering else (0.5, 0.5, 0.5) - color = default_color + # make sure the list is not empty, so that we reset all lines + if len(parts_to_paint) == 0: + parts_to_paint.append(None) - if part is not None: - part_view = workbench.partsCache.getPart2DView(view, part) + for part in parts_to_paint: + default_line_thickness = 0.05 + line_thickness = default_line_thickness - center = self.computePartCenter(view, part) - - if self.isNewPartInView(view, part): - line_thickness = 0.2 - color = (0, 0, 0) + default_color = (0.0, 0.0, 0.0) if fast_rendering else (0.5, 0.5, 0.5) + color = default_color - if self.enable_selected_part_highlight: - for balloon in selected_balloons: - if part == self.getBalloonSourcePart(balloon): - color = (0.0, 0.85, 0.0) # selection highlighting - - # iterate edges of actual view and highlight matching edges - for edgeIdx in range(10000): - hasEdge = False - try: - edge = view.getEdgeByIndex(edgeIdx) - hasEdge = True - except: - pass - if not hasEdge: - break + if part is not None: + part_view = workbench.partsCache.getPart2DView(view, part) + + center = self.computePartCenter(view, part) + + if self.isNewPartInView(view, part): + line_thickness = 0.2 + color = (0, 0, 0) + + if self.enable_selected_part_highlight: + for balloon in selected_balloons: + if part == self.getBalloonSourcePart(balloon): + color = (0.0, 0.85, 0.0) # selection highlighting - is_edge_of_part = False - if part is not None and (not hasattr(edge.Curve, 'Degree') or edge.Curve.Degree == 1) and len(edge.Vertexes) == 2: - edgeData = [ - edge.Vertexes[0].X - center.x, - edge.Vertexes[0].Y - center.y, - edge.Vertexes[1].X - center.x, - edge.Vertexes[1].Y - center.y - ] - v0 = App.Vector(edgeData[0], edgeData[1]) - v1 = App.Vector(edgeData[2], edgeData[3]) + # iterate edges of actual view and highlight matching edges + for edgeIdx in range(10000): + hasEdge = False + try: + edge = view.getEdgeByIndex(edgeIdx) + hasEdge = True + except: + pass + if not hasEdge: + break - for line in part_view.cached_lines: - l0 = App.Vector(line[0], line[1]) - l1 = App.Vector(line[2], line[3]) - #d = abs(edgeData[0] - line[0]) + abs(edgeData[1] - line[1]) + abs(edgeData[2] - line[2]) + abs(edgeData[3] - line[3]) - d = v0.distanceToLineSegment(l0, l1).Length + v1.distanceToLineSegment(l0, l1).Length - if d < 0.01: - is_edge_of_part = True - break + is_edge_of_part = False + if part is not None and (not hasattr(edge.Curve, 'Degree') or edge.Curve.Degree == 1) and len(edge.Vertexes) == 2: + edgeData = [ + edge.Vertexes[0].X - center.x, + edge.Vertexes[0].Y - center.y, + edge.Vertexes[1].X - center.x, + edge.Vertexes[1].Y - center.y + ] + v0 = App.Vector(edgeData[0], edgeData[1]) + v1 = App.Vector(edgeData[2], edgeData[3]) - if is_edge_of_part: - view.formatGeometricEdge(edgeIdx,1,line_thickness,color,True) - elif is_first_part: - # reset edge format - view.formatGeometricEdge(edgeIdx,1,default_line_thickness,default_color,True) - - is_first_part = False - - view.requestPaint() - + for line in part_view.cached_lines: + l0 = App.Vector(line[0], line[1]) + l1 = App.Vector(line[2], line[3]) + #d = abs(edgeData[0] - line[0]) + abs(edgeData[1] - line[1]) + abs(edgeData[2] - line[2]) + abs(edgeData[3] - line[3]) + d = v0.distanceToLineSegment(l0, l1).Length + v1.distanceToLineSegment(l0, l1).Length + if d < 0.01: + is_edge_of_part = True + break + + if is_edge_of_part: + view.formatGeometricEdge(edgeIdx,1,line_thickness,color,True) + elif is_first_part: + # reset edge format + view.formatGeometricEdge(edgeIdx,1,default_line_thickness,default_color,True) + + is_first_part = False + + view.requestPaint() + + def rasterizeView(self, view, image_file_name): + from pivy import coin + import os + + print('Rasterizing ' + view.Label + " to " + image_file_name + "...") + + dir = os.path.dirname(image_file_name) + if not os.path.exists(dir): + os.makedirs(dir) + + doc = App.newDocument('tmp_raster', hidden=False, temp=False) + for part in view.XSource: + link = doc.addObject('App::Link', part.Name) + link.Label = part.Label + if part.TypeId == 'App::Link': + link.LinkedObject = part.LinkedObject + link.Placement = part.Placement + else: + link.LinkedObject = part + + docView = Gui.getDocument(doc.Name).mdiViewsOfType('Gui::View3DInventor')[0] + + cam = docView.getCameraNode() + + rot = coin.SbRotation(coin.SbVec3f(1,0,0), coin.SbVec3f(view.XDirection.x,view.XDirection.y,view.XDirection.z)) + rot *= coin.SbRotation(coin.SbVec3f(0,0,1), coin.SbVec3f(view.Direction.x,view.Direction.y,view.Direction.z)) + cam.orientation.setValue(rot) + + docView.fitAll() + + docView.saveImage(image_file_name, 4096, 4096, "#ffffff") + + App.closeDocument(doc.Name) + def updateBalloonCursor(self, view): selected_balloons = [] for obj in Gui.Selection.getSelection(): @@ -227,7 +287,7 @@ class TechDrawExtensions: if doc != Gui.ActiveDocument.Document: raise Exception("Current view is not for the same document as TechDraw view " + view.Name) activeView = Gui.ActiveDocument.ActiveView - if str(type(activeView)) != "": + if str(type(activeView)) not in ["", ""]: raise Exception("Current view is not a 3D view") cam = activeView.getCameraNode() @@ -408,8 +468,11 @@ class TechDrawExtensions: return None def forceRedrawPage(self, page, callback = None): + needPageUpdate = False for view in page.Views: if view.TypeId == 'TechDraw::DrawViewPart' and 'Assembly_handbook_PreviousStepView' in view.PropertiesList: + if 'Assembly_handbook_RasterView' not in view.PropertiesList or not view.Assembly_handbook_RasterView: + needPageUpdate = True self.refreshView(view) elif view.TypeId == 'TechDraw::DrawViewBalloon': if view.ViewObject.Visibility: @@ -425,7 +488,7 @@ class TechDrawExtensions: view.ViewObject.Visibility = True view.ViewObject.Visibility = False - if page.KeepUpdated: + if page.KeepUpdated or not needPageUpdate: for view in page.Views: if view.TypeId != 'TechDraw::DrawViewPart': view.recompute()