forked from youen/assembly_handbook
fixed bugs
This commit is contained in:
parent
137b73fea1
commit
f9d58c66fc
@ -21,6 +21,8 @@ class AHB_View_Annotate:
|
|||||||
if view.TypeId != 'TechDraw::DrawViewPart':
|
if view.TypeId != 'TechDraw::DrawViewPart':
|
||||||
raise Exception("Selected object is not a TechDraw view")
|
raise Exception("Selected object is not a TechDraw view")
|
||||||
|
|
||||||
|
overlay_view = workbench.techDrawExtensions.getOverlayView(view)
|
||||||
|
|
||||||
doc = view.Document
|
doc = view.Document
|
||||||
|
|
||||||
page = workbench.techDrawExtensions.getViewPage(view)
|
page = workbench.techDrawExtensions.getViewPage(view)
|
||||||
@ -30,7 +32,7 @@ class AHB_View_Annotate:
|
|||||||
# Remove balloons referencing missing objects
|
# Remove balloons referencing missing objects
|
||||||
for balloon in page.Views:
|
for balloon in page.Views:
|
||||||
if balloon.TypeId == 'TechDraw::DrawViewBalloon' and "Assembly_handbook_Source" in balloon.PropertiesList:
|
if balloon.TypeId == 'TechDraw::DrawViewBalloon' and "Assembly_handbook_Source" in balloon.PropertiesList:
|
||||||
if balloon.SourceView != view: continue
|
if balloon.SourceView != view and balloon.SourceView != overlay_view: continue
|
||||||
partLink = workbench.techDrawExtensions.getBalloonSourcePart(balloon)
|
partLink = workbench.techDrawExtensions.getBalloonSourcePart(balloon)
|
||||||
if partLink is None or partLink not in view.XSource:
|
if partLink is None or partLink not in view.XSource:
|
||||||
ref_name = "<no ref>"
|
ref_name = "<no ref>"
|
||||||
@ -47,13 +49,9 @@ class AHB_View_Annotate:
|
|||||||
# Search an existing balloon to update
|
# Search an existing balloon to update
|
||||||
for obj in page.Views:
|
for obj in page.Views:
|
||||||
if obj.TypeId == 'TechDraw::DrawViewBalloon' and workbench.techDrawExtensions.getBalloonSourcePart(obj) == partLink:
|
if obj.TypeId == 'TechDraw::DrawViewBalloon' and workbench.techDrawExtensions.getBalloonSourcePart(obj) == partLink:
|
||||||
if obj.SourceView != view: continue
|
if obj.SourceView != overlay_view: continue
|
||||||
balloon = obj
|
balloon = obj
|
||||||
|
|
||||||
overlay_view = doc.getObject(view.Name + '_overlay')
|
|
||||||
if overlay_view is None:
|
|
||||||
overlay_view = view
|
|
||||||
|
|
||||||
# Create a new balloon if needed
|
# Create a new balloon if needed
|
||||||
if balloon is None:
|
if balloon is None:
|
||||||
partName = partLink.Name
|
partName = partLink.Name
|
||||||
|
@ -7,6 +7,21 @@ class RasterView:
|
|||||||
doc = view.Document
|
doc = view.Document
|
||||||
self.image_file_name = doc.FileName.replace('.FCStd', '') + '_raster/' + view.Name + '.png'
|
self.image_file_name = doc.FileName.replace('.FCStd', '') + '_raster/' + view.Name + '.png'
|
||||||
|
|
||||||
|
def init_image_projection(self):
|
||||||
|
doc = self.source_view.Document
|
||||||
|
image_name = self.source_view.Label + "_raster"
|
||||||
|
image = doc.getObject(image_name)
|
||||||
|
if image is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.image_view = image
|
||||||
|
|
||||||
|
if image.Assembly_handbook_ViewVolumeWidth > 0:
|
||||||
|
self._precompute_image_projection()
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def init_image(self):
|
def init_image(self):
|
||||||
workbench = Gui.getWorkbench("AssemblyHandbookWorkbench") #: :type workbench: AssemblyHandbookWorkbench
|
workbench = Gui.getWorkbench("AssemblyHandbookWorkbench") #: :type workbench: AssemblyHandbookWorkbench
|
||||||
|
|
||||||
@ -34,9 +49,9 @@ class RasterView:
|
|||||||
self.image_view = image
|
self.image_view = image
|
||||||
|
|
||||||
if image.Assembly_handbook_ViewVolumeWidth > 0:
|
if image.Assembly_handbook_ViewVolumeWidth > 0:
|
||||||
self.init_image_projection()
|
self._precompute_image_projection()
|
||||||
|
|
||||||
def init_image_projection(self):
|
def _precompute_image_projection(self):
|
||||||
YDirection = self.source_view.Direction.cross(self.source_view.XDirection)
|
YDirection = self.source_view.Direction.cross(self.source_view.XDirection)
|
||||||
|
|
||||||
self.image_x_dir = self.source_view.XDirection / self.image_view.Assembly_handbook_ViewVolumeWidth
|
self.image_x_dir = self.source_view.XDirection / self.image_view.Assembly_handbook_ViewVolumeWidth
|
||||||
@ -51,6 +66,15 @@ class RasterView:
|
|||||||
offset = self.image_view.Assembly_handbook_ViewVolumeOffset
|
offset = self.image_view.Assembly_handbook_ViewVolumeOffset
|
||||||
return App.Vector(self.image_x_dir.dot(point3d) + offset.x, self.image_y_dir.dot(point3d) + offset.y, self.image_z_dir.dot(point3d) + offset.z)
|
return App.Vector(self.image_x_dir.dot(point3d) + offset.x, self.image_y_dir.dot(point3d) + offset.y, self.image_z_dir.dot(point3d) + offset.z)
|
||||||
|
|
||||||
|
def project3DPointToSourceView(self, point3d):
|
||||||
|
offset = self.image_view.Assembly_handbook_ViewVolumeOffset
|
||||||
|
offset = App.Vector((offset.x-0.5) * self.image_view.Assembly_handbook_ViewVolumeWidth, (offset.y-0.5) * self.image_view.Assembly_handbook_ViewVolumeHeight, (offset.z-0.5) * self.image_view.Assembly_handbook_ViewVolumeDepth)
|
||||||
|
#image_view_point = App.Vector(self.image_x_dir.dot(point3d), self.image_y_dir.dot(point3d), self.image_z_dir.dot(point3d))
|
||||||
|
#return App.Vector(image_view_point.x * self.image_view.Assembly_handbook_ViewVolumeWidth, image_view_point.y * self.image_view.Assembly_handbook_ViewVolumeHeight, 0)
|
||||||
|
|
||||||
|
YDirection = self.source_view.Direction.cross(self.source_view.XDirection)
|
||||||
|
return App.Vector(self.source_view.XDirection.dot(point3d) + offset.x, YDirection.dot(point3d) + offset.y, self.image_z_dir.dot(point3d) + offset.z)
|
||||||
|
|
||||||
def projectImageViewPointTo3D(self, point2d):
|
def projectImageViewPointTo3D(self, point2d):
|
||||||
offset = self.image_view.Assembly_handbook_ViewVolumeOffset
|
offset = self.image_view.Assembly_handbook_ViewVolumeOffset
|
||||||
p = point2d - offset
|
p = point2d - offset
|
||||||
@ -96,25 +120,15 @@ class RasterView:
|
|||||||
self.image_view.Assembly_handbook_ViewVolumeHeight = viewVolume.getHeight()
|
self.image_view.Assembly_handbook_ViewVolumeHeight = viewVolume.getHeight()
|
||||||
self.image_view.Assembly_handbook_ViewVolumeDepth = viewVolume.getDepth()
|
self.image_view.Assembly_handbook_ViewVolumeDepth = viewVolume.getDepth()
|
||||||
|
|
||||||
sb_offset = viewVolume.projectToScreen(coin.SbVec3f(0,0,0))
|
|
||||||
self.image_view.Assembly_handbook_ViewVolumeOffset = App.Vector(sb_offset[0], sb_offset[1], sb_offset[2])
|
|
||||||
|
|
||||||
self.init_image_projection()
|
|
||||||
|
|
||||||
docView.saveImage(self.image_file_name, 4096, 4096, "#ffffff")
|
docView.saveImage(self.image_file_name, 4096, 4096, "#ffffff")
|
||||||
|
|
||||||
with Image.open(self.image_file_name) as img:
|
with Image.open(self.image_file_name) as img:
|
||||||
original_size = img.size
|
original_size = img.size
|
||||||
|
|
||||||
p2dA = self.project3DPointToImageView(App.Vector(0,0,0))
|
|
||||||
p2dB = self.project3DPointToImageView(view.XDirection)
|
|
||||||
imageScale = view.Scale / (p2dB.x - p2dA.x) / original_size[0] * 10
|
|
||||||
#print('imageScale', imageScale)
|
|
||||||
|
|
||||||
bg = Image.new(img.mode, img.size, '#ffffff') # fills an image with the background color
|
bg = Image.new(img.mode, img.size, '#ffffff') # fills an image with the background color
|
||||||
diff = ImageChops.difference(img, bg) # diff between the actual image and the background color
|
diff = ImageChops.difference(img, bg) # diff between the actual image and the background color
|
||||||
bbox = diff.getbbox() # finds border size (non-black portion of the image)
|
bbox = diff.getbbox() # finds border size (non-black portion of the image)
|
||||||
print(bbox)
|
#print(bbox)
|
||||||
#image_center = (bbox[0] + (bbox[2] - bbox[0])/2 - img.size[0]/2, bbox[1] + (bbox[3] - bbox[1])/2 - img.size[1]/2)
|
#image_center = (bbox[0] + (bbox[2] - bbox[0])/2 - img.size[0]/2, bbox[1] + (bbox[3] - bbox[1])/2 - img.size[1]/2)
|
||||||
#print(image_center)
|
#print(image_center)
|
||||||
img = img.crop(bbox)
|
img = img.crop(bbox)
|
||||||
@ -135,6 +149,17 @@ class RasterView:
|
|||||||
#debugPoint(App.Vector(131.23702882966705, -655.0000021095163, 145.21130178331268))
|
#debugPoint(App.Vector(131.23702882966705, -655.0000021095163, 145.21130178331268))
|
||||||
|
|
||||||
img.save(self.image_file_name)
|
img.save(self.image_file_name)
|
||||||
|
|
||||||
|
sb_offset = viewVolume.projectToScreen(coin.SbVec3f(0,0,0))
|
||||||
|
crop_offset = App.Vector(((bbox[0] + bbox[2])/2 - original_size[0]/2)/original_size[0], ((bbox[1] + bbox[3])/2 - original_size[1]/2)/original_size[1], 0)
|
||||||
|
self.image_view.Assembly_handbook_ViewVolumeOffset = App.Vector(sb_offset[0] - crop_offset.x, sb_offset[1] + crop_offset.y, sb_offset[2])
|
||||||
|
|
||||||
|
self._precompute_image_projection()
|
||||||
|
|
||||||
|
p2dA = self.project3DPointToImageView(App.Vector(0,0,0))
|
||||||
|
p2dB = self.project3DPointToImageView(view.XDirection)
|
||||||
|
imageScale = view.Scale / (p2dB.x - p2dA.x) / original_size[0] * 10
|
||||||
|
#print('imageScale', imageScale)
|
||||||
|
|
||||||
App.closeDocument(doc.Name)
|
App.closeDocument(doc.Name)
|
||||||
|
|
||||||
|
@ -16,6 +16,9 @@ class CursorItem(QtGui.QGraphicsItem):
|
|||||||
self.size = 100.0
|
self.size = 100.0
|
||||||
self.view = view
|
self.view = view
|
||||||
|
|
||||||
|
def removeSceneEventFilter(self, a, b):
|
||||||
|
print('removeSceneEventFilter', a, b)
|
||||||
|
|
||||||
def onViewPosChange(self, callback):
|
def onViewPosChange(self, callback):
|
||||||
self.viewPosChangeCallback = callback
|
self.viewPosChangeCallback = callback
|
||||||
|
|
||||||
@ -173,11 +176,33 @@ class TechDrawExtensions:
|
|||||||
overlay.Scale = view.Scale
|
overlay.Scale = view.Scale
|
||||||
overlay.ViewObject.LineWidth = 0.01
|
overlay.ViewObject.LineWidth = 0.01
|
||||||
|
|
||||||
|
# migrate balloons from source view to overlay
|
||||||
for balloon in page.Views:
|
for balloon in page.Views:
|
||||||
if balloon.TypeId == 'TechDraw::DrawViewBalloon' and "Assembly_handbook_Source" in balloon.PropertiesList and balloon.SourceView == view:
|
if balloon.TypeId == 'TechDraw::DrawViewBalloon' and "Assembly_handbook_Source" in balloon.PropertiesList and balloon.SourceView == view:
|
||||||
if balloon.SourceView == view:
|
if balloon.SourceView == view:
|
||||||
|
old_source = balloon.Assembly_handbook_Source
|
||||||
|
old_OriginOffsetX = balloon.Assembly_handbook_OriginOffsetX
|
||||||
|
old_OriginOffsetY = balloon.Assembly_handbook_OriginOffsetY
|
||||||
|
old_X = balloon.X
|
||||||
|
old_Y = balloon.Y
|
||||||
|
old_Visibility = balloon.ViewObject.Visibility
|
||||||
|
balloonName = balloon.Name
|
||||||
|
|
||||||
|
doc.removeObject(balloon.Name)
|
||||||
|
|
||||||
|
balloon = doc.addObject("TechDraw::DrawViewBalloon", balloonName)
|
||||||
balloon.SourceView = overlay
|
balloon.SourceView = overlay
|
||||||
|
balloon.addProperty("App::PropertyXLink", "Assembly_handbook_Source", "Assembly_handbook")
|
||||||
|
balloon.Assembly_handbook_Source = old_source
|
||||||
|
balloon.addProperty("App::PropertyFloat", "Assembly_handbook_OriginOffsetX", "Assembly_handbook")
|
||||||
|
balloon.addProperty("App::PropertyFloat", "Assembly_handbook_OriginOffsetY", "Assembly_handbook")
|
||||||
|
balloon.Assembly_handbook_OriginOffsetX = old_OriginOffsetX
|
||||||
|
balloon.Assembly_handbook_OriginOffsetY = old_OriginOffsetY
|
||||||
page.addView(balloon)
|
page.addView(balloon)
|
||||||
|
self.updateBalloon(balloon)
|
||||||
|
balloon.X = old_X
|
||||||
|
balloon.Y = old_Y
|
||||||
|
balloon.ViewObject.Visibility = old_Visibility
|
||||||
balloon.recompute()
|
balloon.recompute()
|
||||||
|
|
||||||
page.KeepUpdated = True # once we have hidden the source view, there should be no performance issue
|
page.KeepUpdated = True # once we have hidden the source view, there should be no performance issue
|
||||||
@ -293,6 +318,13 @@ class TechDrawExtensions:
|
|||||||
selected_balloons.append(obj)
|
selected_balloons.append(obj)
|
||||||
|
|
||||||
cursor = self.view_cursors.get(view, None)
|
cursor = self.view_cursors.get(view, None)
|
||||||
|
if cursor is not None:
|
||||||
|
try:
|
||||||
|
cursor.x() # this can throw an exception if the Qt item has been deleted (for example when closing the page)
|
||||||
|
except Exception as ex:
|
||||||
|
print("Re-generating cursor...")
|
||||||
|
cursor = None
|
||||||
|
|
||||||
if cursor is None:
|
if cursor is None:
|
||||||
cursor = CursorItem(view = view)
|
cursor = CursorItem(view = view)
|
||||||
TDG.addQGIToView(view, cursor);
|
TDG.addQGIToView(view, cursor);
|
||||||
@ -412,7 +444,7 @@ class TechDrawExtensions:
|
|||||||
view = balloon.SourceView
|
view = balloon.SourceView
|
||||||
self.updateBalloonCursor(view)
|
self.updateBalloonCursor(view)
|
||||||
if self.enable_selected_part_highlight:
|
if self.enable_selected_part_highlight:
|
||||||
self.repaint(view) # disabled for now, for performance reasons
|
self.repaint(view)
|
||||||
|
|
||||||
def onBalloonChanged(self, obj, prop):
|
def onBalloonChanged(self, obj, prop):
|
||||||
# Avoid reentry
|
# Avoid reentry
|
||||||
@ -496,6 +528,10 @@ class TechDrawExtensions:
|
|||||||
needPageUpdate = False
|
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 not 'Assembly_handbook_RasterView' in view.PropertiesList:
|
||||||
|
view.addProperty("App::PropertyBool", "Assembly_handbook_RasterView", "Assembly_handbook")
|
||||||
|
view.Assembly_handbook_RasterView = True
|
||||||
|
|
||||||
if 'Assembly_handbook_RasterView' not in view.PropertiesList or not view.Assembly_handbook_RasterView:
|
if 'Assembly_handbook_RasterView' not in view.PropertiesList or not view.Assembly_handbook_RasterView:
|
||||||
needPageUpdate = True
|
needPageUpdate = True
|
||||||
self.refreshView(view)
|
self.refreshView(view)
|
||||||
@ -534,7 +570,24 @@ class TechDrawExtensions:
|
|||||||
callback()
|
callback()
|
||||||
QTimer.singleShot(10, restoreKeepUpdated)
|
QTimer.singleShot(10, restoreKeepUpdated)
|
||||||
|
|
||||||
|
def getSourceView(self, view):
|
||||||
|
if view.Name.endswith('_overlay'):
|
||||||
|
view = view.Document.getObject(view.Name[0:-8])
|
||||||
|
if view is None:
|
||||||
|
raise Exception("Can't find source view of " + view.Name)
|
||||||
|
|
||||||
|
return view
|
||||||
|
|
||||||
|
def getOverlayView(self, view):
|
||||||
|
if view.Name.endswith('_overlay'):
|
||||||
|
return view
|
||||||
|
|
||||||
|
overlay = view.Document.getObject(view.Name + '_overlay')
|
||||||
|
return overlay if overlay is not None else view
|
||||||
|
|
||||||
def computePartCenter(self, view, obj):
|
def computePartCenter(self, view, obj):
|
||||||
|
view = self.getSourceView(view)
|
||||||
|
|
||||||
if obj.TypeId == 'App::Link':
|
if obj.TypeId == 'App::Link':
|
||||||
partLink = obj
|
partLink = obj
|
||||||
objectCenterWorld = partLink.LinkPlacement.Matrix.multiply(partLink.LinkedObject.Shape.CenterOfGravity)
|
objectCenterWorld = partLink.LinkPlacement.Matrix.multiply(partLink.LinkedObject.Shape.CenterOfGravity)
|
||||||
@ -561,6 +614,12 @@ class TechDrawExtensions:
|
|||||||
return self.projectPoint(view, objectCenterWorld)
|
return self.projectPoint(view, objectCenterWorld)
|
||||||
|
|
||||||
def projectPoint(self, view, point3d):
|
def projectPoint(self, view, point3d):
|
||||||
|
if 'Assembly_handbook_RasterView' in view.PropertiesList or view.Assembly_handbook_RasterView:
|
||||||
|
from ahb_raster_view import RasterView
|
||||||
|
raster_view = RasterView(view)
|
||||||
|
if raster_view.init_image_projection():
|
||||||
|
return raster_view.project3DPointToSourceView(point3d)
|
||||||
|
|
||||||
# DrawViewPart::projectPoint should be exposed to python in freecad 0.21, but for 0.20 we have to use a workaround
|
# DrawViewPart::projectPoint should be exposed to python in freecad 0.21, but for 0.20 we have to use a workaround
|
||||||
view_cache = self.getViewCache(view)
|
view_cache = self.getViewCache(view)
|
||||||
if view_cache.projected_origin is None:
|
if view_cache.projected_origin is None:
|
||||||
|
Loading…
Reference in New Issue
Block a user