alternative rendering method (rasterization) ; wip

This commit is contained in:
Youen 2022-12-22 22:34:37 +01:00
parent 05e7da16a5
commit be9ff003e3
2 changed files with 164 additions and 100 deletions

View File

@ -64,6 +64,7 @@ class AHB_New_Step:
view = doc.addObject('TechDraw::DrawViewPart', 'View') view = doc.addObject('TechDraw::DrawViewPart', 'View')
view.Perspective = False view.Perspective = False
view.addProperty("App::PropertyString", "Assembly_handbook_PreviousStepView", "Assembly_handbook") view.addProperty("App::PropertyString", "Assembly_handbook_PreviousStepView", "Assembly_handbook")
view.addProperty("App::PropertyBool", "Assembly_handbook_RasterView", "Assembly_handbook")
if prev_view is None: if prev_view is None:
try: try:
workbench.techDrawExtensions.setCurrentViewDirection(view) workbench.techDrawExtensions.setCurrentViewDirection(view)

View File

@ -94,112 +94,172 @@ class TechDrawExtensions:
for view in to_repaint: for view in to_repaint:
#print("Repainting " + view.Name) #print("Repainting " + view.Name)
page = self.getViewPage(view)
view_cache = self.getViewCache(view) view_cache = self.getViewCache(view)
view_cache.reset() view_cache.reset()
doc = view.Document doc = view.Document
fast_rendering = False if not 'Assembly_handbook_RasterView' in view.PropertiesList:
#try: view.addProperty("App::PropertyBool", "Assembly_handbook_RasterView", "Assembly_handbook")
# fast_rendering = view.Assembly_handbook_FastRendering
#except:
# pass
if view.CoarseView: if view.Assembly_handbook_RasterView:
fast_rendering = True 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")
selected_balloons = [] if not image in page.Views:
for obj in Gui.Selection.getSelection(): page.addView(image)
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 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
if not fast_rendering: image_file_name = doc.FileName.replace('.FCStd', '') + '_raster/' + view.Name + '.png'
is_first_part = True 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
parts_to_paint = [] if view.CoarseView:
fast_rendering = True
# repaint parts that are highlighted by selection selected_balloons = []
if self.enable_selected_part_highlight: for obj in Gui.Selection.getSelection():
for balloon in selected_balloons: if obj.TypeId == 'TechDraw::DrawViewBalloon' and obj.SourceView == view and 'Assembly_handbook_Source' in obj.PropertiesList:
part = self.getBalloonSourcePart(balloon) selected_balloons.append(obj)
if part in view.XSource:
#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) parts_to_paint.append(part)
# repaint parts that are new in this step (thick line) # make sure the list is not empty, so that we reset all lines
prev_view = None if len(parts_to_paint) == 0:
if 'Assembly_handbook_PreviousStepView' in view.PropertiesList: parts_to_paint.append(None)
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 for part in parts_to_paint:
if len(parts_to_paint) == 0: default_line_thickness = 0.05
parts_to_paint.append(None) line_thickness = default_line_thickness
for part in parts_to_paint: default_color = (0.0, 0.0, 0.0) if fast_rendering else (0.5, 0.5, 0.5)
default_line_thickness = 0.05 color = default_color
line_thickness = default_line_thickness
default_color = (0.0, 0.0, 0.0) if fast_rendering else (0.5, 0.5, 0.5) if part is not None:
color = default_color part_view = workbench.partsCache.getPart2DView(view, part)
if part is not None: center = self.computePartCenter(view, part)
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.isNewPartInView(view, part): if self.enable_selected_part_highlight:
line_thickness = 0.2 for balloon in selected_balloons:
color = (0, 0, 0) if part == self.getBalloonSourcePart(balloon):
color = (0.0, 0.85, 0.0) # selection highlighting
if self.enable_selected_part_highlight: # iterate edges of actual view and highlight matching edges
for balloon in selected_balloons: for edgeIdx in range(10000):
if part == self.getBalloonSourcePart(balloon): hasEdge = False
color = (0.0, 0.85, 0.0) # selection highlighting try:
edge = view.getEdgeByIndex(edgeIdx)
hasEdge = True
except:
pass
if not hasEdge:
break
# iterate edges of actual view and highlight matching edges is_edge_of_part = False
for edgeIdx in range(10000): if part is not None and (not hasattr(edge.Curve, 'Degree') or edge.Curve.Degree == 1) and len(edge.Vertexes) == 2:
hasEdge = False edgeData = [
try: edge.Vertexes[0].X - center.x,
edge = view.getEdgeByIndex(edgeIdx) edge.Vertexes[0].Y - center.y,
hasEdge = True edge.Vertexes[1].X - center.x,
except: edge.Vertexes[1].Y - center.y
pass ]
if not hasEdge: v0 = App.Vector(edgeData[0], edgeData[1])
break v1 = App.Vector(edgeData[2], edgeData[3])
is_edge_of_part = False for line in part_view.cached_lines:
if part is not None and (not hasattr(edge.Curve, 'Degree') or edge.Curve.Degree == 1) and len(edge.Vertexes) == 2: l0 = App.Vector(line[0], line[1])
edgeData = [ l1 = App.Vector(line[2], line[3])
edge.Vertexes[0].X - center.x, #d = abs(edgeData[0] - line[0]) + abs(edgeData[1] - line[1]) + abs(edgeData[2] - line[2]) + abs(edgeData[3] - line[3])
edge.Vertexes[0].Y - center.y, d = v0.distanceToLineSegment(l0, l1).Length + v1.distanceToLineSegment(l0, l1).Length
edge.Vertexes[1].X - center.x, if d < 0.01:
edge.Vertexes[1].Y - center.y is_edge_of_part = True
] break
v0 = App.Vector(edgeData[0], edgeData[1])
v1 = App.Vector(edgeData[2], edgeData[3])
for line in part_view.cached_lines: if is_edge_of_part:
l0 = App.Vector(line[0], line[1]) view.formatGeometricEdge(edgeIdx,1,line_thickness,color,True)
l1 = App.Vector(line[2], line[3]) elif is_first_part:
#d = abs(edgeData[0] - line[0]) + abs(edgeData[1] - line[1]) + abs(edgeData[2] - line[2]) + abs(edgeData[3] - line[3]) # reset edge format
d = v0.distanceToLineSegment(l0, l1).Length + v1.distanceToLineSegment(l0, l1).Length view.formatGeometricEdge(edgeIdx,1,default_line_thickness,default_color,True)
if d < 0.01:
is_edge_of_part = True
break
if is_edge_of_part: is_first_part = False
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()
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): def updateBalloonCursor(self, view):
selected_balloons = [] selected_balloons = []
@ -227,7 +287,7 @@ class TechDrawExtensions:
if doc != Gui.ActiveDocument.Document: if doc != Gui.ActiveDocument.Document:
raise Exception("Current view is not for the same document as TechDraw view " + view.Name) raise Exception("Current view is not for the same document as TechDraw view " + view.Name)
activeView = Gui.ActiveDocument.ActiveView activeView = Gui.ActiveDocument.ActiveView
if str(type(activeView)) != "<class 'View3DInventorPy'>": if str(type(activeView)) not in ["<class 'View3DInventorPy'>", "<class 'Gui.View3DInventor'>"]:
raise Exception("Current view is not a 3D view") raise Exception("Current view is not a 3D view")
cam = activeView.getCameraNode() cam = activeView.getCameraNode()
@ -408,8 +468,11 @@ class TechDrawExtensions:
return None return None
def forceRedrawPage(self, page, callback = None): def forceRedrawPage(self, page, callback = None):
needPageUpdate = False
for view in page.Views: for view in page.Views:
if view.TypeId == 'TechDraw::DrawViewPart' and 'Assembly_handbook_PreviousStepView' in view.PropertiesList: 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) self.refreshView(view)
elif view.TypeId == 'TechDraw::DrawViewBalloon': elif view.TypeId == 'TechDraw::DrawViewBalloon':
if view.ViewObject.Visibility: if view.ViewObject.Visibility:
@ -425,7 +488,7 @@ class TechDrawExtensions:
view.ViewObject.Visibility = True view.ViewObject.Visibility = True
view.ViewObject.Visibility = False view.ViewObject.Visibility = False
if page.KeepUpdated: if page.KeepUpdated or not needPageUpdate:
for view in page.Views: for view in page.Views:
if view.TypeId != 'TechDraw::DrawViewPart': if view.TypeId != 'TechDraw::DrawViewPart':
view.recompute() view.recompute()