Set camera view to sketch center

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
freedman
Veteran
Posts: 3440
Joined: Thu Mar 22, 2018 3:02 am
Location: Washington State, USA

Set camera view to sketch center

Post by freedman »

Anyone have some code for a macro that can set the sketch to center screen? I found this (below) to start off, it looks like the thought was to find the object bounds but I want to do a sketch, I have no idea how to use TypeId. I want to be able to run this while in Sketcher. Oh! The problem I'm try to correct is that sketcher will open at the current location, I want the screen to center on the sketch where ever it is located in the model space. Thanks

Code: Select all

def find_centre():
    doc = app.activeDocument()
    if doc is None:
        return app.Vector(0, 0, 0)

    xmax = 0
    xmin = 0
    ymax = 0
    ymin = 0
    zmax = 0
    zmin = 0
    for obj in doc.Objects:
        try:
            if obj.TypeId[:4] == 'Mesh':
                box = obj.Mesh.BoundBox
            elif obj.TypeId[:6] == 'Points':
                box = obj.Points.BoundBox
            elif obj.TypeId[:4] == 'Part':
                box = obj.Shape.BoundBox
            else:
                continue
        except AttributeError:
            continue
        xmax = max(xmax, box.XMax)
        xmin = min(xmin, box.XMin)
        ymax = max(ymax, box.YMax)
        ymin = min(ymin, box.YMin)
        zmax = max(zmax, box.ZMax)
        zmin = min(zmin, box.ZMin)

    return app.Vector((xmax + xmin) / 2, (ymax + ymin) / 2, (zmax + zmin) / 2)
mario52
Veteran
Posts: 4673
Joined: Wed May 16, 2012 2:13 pm

Re: Set camera view to sketch center

Post by mario52 »

hi

How to apply Near and Far clipping from a script?

just modified for object selected (or not) (in sketcher also)

Code: Select all

#https://www.forum.freecadweb.org/viewtopic.php?f=22&t=26391
#How to apply Near and Far clipping from a script?
#https://forum.freecadweb.org/viewtopic.php?f=22&t=40938
#Set camera view to sketch center

view=Gui.ActiveDocument.ActiveView
view.fitAll()

from pivy import coin
try:
    ##### for first Subobject selected
    sel = Gui.Selection.getSelectionEx()[0].SubObjects[0].BoundBox              # sub element BoundBox coordinates
    b=sel
    ##### for first subobject selected
    
    ##### for first Object selected
    #sel = FreeCADGui.Selection.getSelection()[0]
    #b=sel.Shape.BoundBox
    ##### for first Object selected
    
    box=coin.SbBox3f()
    box.setBounds(b.XMin,b.YMin,b.ZMin,b.XMax,b.YMax,b.ZMax)
    
    cam=view.getCameraNode()
    cam.nearDistance.getValue()
    cam.farDistance.getValue() # far distance is quite high
    cam.focalDistance.getValue()
    
    cam.viewBoundingBox(box,1,1) # focuses on the cylinder
    
    cam.nearDistance.getValue()
    cam.farDistance.getValue() # ... but far distance is still quite high and the cube is not clipped away
    cam.focalDistance.getValue()
    
    
    viewer=view.getViewer()
    rm=viewer.getSoRenderManager()
    
    # this does the trick
    rm.setAutoClipping(coin.SoRenderManager.NO_AUTO_CLIPPING)
    
    # now the cube is clipped away
    cam.viewBoundingBox(box,1,1)
except Exception:
    print("Select one object")


EDIT 16/11/2019 15h55 modify the code for selection and focus to SubObjects[0] (first selection)

mario
Maybe you need a special feature, go into Macros_recipes and Code_snippets, Topological_data_scripting.
My macros on Gist.github here complete macros Wiki and forum.
freedman
Veteran
Posts: 3440
Joined: Thu Mar 22, 2018 3:02 am
Location: Washington State, USA

Re: Set camera view to sketch center

Post by freedman »

I will start looking at that, thanks. I need to add to my description of what I want, I'm a little weak on placement wording.
Every sketch that's created has a sketch center and a sketch boundbox, those sketch centers are spread all over as the model is created. I want to focus the camera on the selected (currently opened in sketcher) sketch boundbox, not sketch center. Here is the tricky part, if it's a new sketch then sketch center is where you are currently but if it's an existing sketch then sketch center is probably somewhere else. I feel like Sketcher should know the difference , maybe that's a bug.

Thanks
mario52
Veteran
Posts: 4673
Joined: Wed May 16, 2012 2:13 pm

Re: Set camera view to sketch center

Post by mario52 »

hi

just explanation of operation of the macro, case hexagon :

here (actual) you select the edge5, the boundBox center of edge5 is centred on screen

Code: Select all

    ##### for first Subobject selected
    sel = Gui.Selection.getSelectionEx()[0].SubObjects[0].BoundBox              # sub element BoundBox coordinates
    b=sel
    ##### for first subobject selected


here (uncoment for use it) you select the edge5 or other the boundBox center of the complete sketch is centred on screen

Code: Select all

    ##### for first Object selected
    #sel = FreeCADGui.Selection.getSelection()[0]
    #b=sel.Shape.BoundBox
    ##### for first Object selected
opened in sketcher or not

mario
Maybe you need a special feature, go into Macros_recipes and Code_snippets, Topological_data_scripting.
My macros on Gist.github here complete macros Wiki and forum.
freedman
Veteran
Posts: 3440
Joined: Thu Mar 22, 2018 3:02 am
Location: Washington State, USA

Re: Set camera view to sketch center

Post by freedman »

I don't see that working. I made a test file that has a feature on each end of a bar. The way I test: Zoom in to the left feature sketch, now click to open the right feature sketch, the camera view should zoom to the other end of the bar to view the right sketch boundbox. What I see running your code: The camera view moves to model off center.
Attachments
2_sketch_bar.FCStd
(20.75 KiB) Downloaded 29 times
mario52
Veteran
Posts: 4673
Joined: Wed May 16, 2012 2:13 pm

Re: Set camera view to sketch center

Post by mario52 »

hi

try this : select the sketch run the macro the sketch is edited and centred

Code: Select all

#https://www.forum.freecadweb.org/viewtopic.php?f=22&t=26391
#How to apply Near and Far clipping from a script?
#https://forum.freecadweb.org/viewtopic.php?f=22&t=40938
#Set camera view to sketch center
#https://forum.freecadweb.org/viewtopic.php?t=24788
#Sketch enter Edit Mode by Python Script

try:
    view=Gui.ActiveDocument.ActiveView
    view.fitAll()
    
    from pivy import coin
    sel0 = Gui.Selection.getSelection()
#    Gui.Selection.addSelection(App.ActiveDocument.getObject(sel0[0].Name))
    b = sel0[0].Shape.BoundBox
    
    box=coin.SbBox3f()
    box.setBounds(b.XMin,b.YMin,b.ZMin,b.XMax,b.YMax,b.ZMax)
    
    cam=view.getCameraNode()
    cam.nearDistance.getValue()
    cam.farDistance.getValue() # far distance is quite high
    cam.focalDistance.getValue()
    
    cam.viewBoundingBox(box,1,1) # focuses on the cylinder
    
    Gui.ActiveDocument.setEdit(Gui.Selection.getSelectionEx()[0].Object)    # Edit the Object
except Exception:
    print("Error")


mario
Maybe you need a special feature, go into Macros_recipes and Code_snippets, Topological_data_scripting.
My macros on Gist.github here complete macros Wiki and forum.
freedman
Veteran
Posts: 3440
Joined: Thu Mar 22, 2018 3:02 am
Location: Washington State, USA

Re: Set camera view to sketch center

Post by freedman »

That works great! Thank you :D

Here is a small macro I use to test, I run your code as soon as we go into sketcher. You can see I connect to a workbench change and have your code running as I enter sketcher.
Thank you

Code: Select all

import FreeCAD
import FreeCADGui
import time
from pivy import coin
import FreeCAD as App, FreeCADGui 
from PySide import QtGui,QtCore
import FreeCAD as app
import FreeCADGui as gui

class VariableWatcher(QtGui.QDockWidget):

    def __init__(self):
        super(VariableWatcher, self).__init__()
        self.setParent(Gui.getMainWindow())
        self.setWindowFlags( QtCore.Qt.WindowStaysOnTopHint)
        self.setStyleSheet("margin:10px; border:10px solid; ")
        self.setWindowTitle("Test")
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
        self.initUI()
        mw=Gui.getMainWindow()
        mw.workbenchActivated.connect(self.wbChange)


    def initUI(self):
      
       self.layout = QtGui.QVBoxLayout()
       self.setGeometry(100, 180, 60, 800) 
       self.show()
    
    def wbChange(self):
        active = Gui.activeWorkbench().__class__.__name__
        if active == "SketcherWorkbench":
            try:
                view=Gui.ActiveDocument.ActiveView
                view.fitAll()
                
                from pivy import coin
                sel0 = Gui.Selection.getSelection()
                #sel0=Gui.Selection.addSelection(App.ActiveDocument.getObject(sel0[0].Name))
                b = sel0[0].Shape.BoundBox
                
                box=coin.SbBox3f()
                box.setBounds(b.XMin,b.YMin,b.ZMin,b.XMax,b.YMax,b.ZMax)
                
                cam=view.getCameraNode()
                cam.nearDistance.getValue()
                cam.farDistance.getValue() # far distance is quite high
                cam.focalDistance.getValue()
                
                cam.viewBoundingBox(box,1,1) # focuses on the cylinder
                
          #      Gui.ActiveDocument.setEdit(Gui.Selection.getSelectionEx()[0].Object)    # Edit the Object
            except Exception:
                print("Error")

    def closeEvent(self, event):
        self.close()

form = VariableWatcher()	
I just want to say this is amazing, I can center on any sketch while in sketcher. Wow!
Last edited by freedman on Mon Nov 18, 2019 7:03 pm, edited 1 time in total.
freedman
Veteran
Posts: 3440
Joined: Thu Mar 22, 2018 3:02 am
Location: Washington State, USA

Re: Set camera view to sketch center

Post by freedman »

I have a small zooming issue on my big monitor but other than that it seems to work great. Thanks very much for your time mario.

I am cranking all this into my 2D3D macro to be posted soon. :)
Last edited by freedman on Mon Nov 18, 2019 7:04 pm, edited 1 time in total.
freedman
Veteran
Posts: 3440
Joined: Thu Mar 22, 2018 3:02 am
Location: Washington State, USA

Re: Set camera view to sketch center

Post by freedman »

I see what's going on. I run FreeCAD on dual monitors; one is the full graphic window and the other panels. Apparently coin thinks my graphic screen is both monitors so it centers things messed up. Pretty sure I can add some calcs to the setBounds and make things right. I will try to do a Right and Left version for the dual monitor folks. I will also look at Coin to check for a different call.

Mario, is there an easy way to switch the camera to the opposite side, many times the sketches are based on the other side and I can install a button to flip the view.

Thanks again.
mario52
Veteran
Posts: 4673
Joined: Wed May 16, 2012 2:13 pm

Re: Set camera view to sketch center

Post by mario52 »

hi
freedman wrote: Mon Nov 18, 2019 4:49 am is there an easy way to switch the camera to the opposite side, many times the sketches are based on the other side and I can install a button to flip the view.
normally (0,0,-1) (and (0,0,1)) but no result

here little code to play with camera and collection snippets picked in forum and links for study

Code: Select all

# -*- coding: utf-8 -*-
#from __future__ import unicode_literals
#
__title__   = "Titre"
__author__  = "Auteur"
__url__     = "http://www.freecadweb.org/index-fr.html"
__Wiki__    = "http://www.freecadweb.org/wiki/index.php?title="
__version__ = "00.00"
__date__    = "04/05/2019"

import PySide2
from PySide2 import QtGui ,QtCore, QtWidgets
from PySide2.QtGui import *
from PySide2.QtCore import *
global camera

from pivy import coin

Gui = FreeCADGui
App = FreeCAD


def errorDialog(msg):
    diag = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical,u"Error Message",msg )
#    diag.setWindowModality(QtCore.Qt.ApplicationModal)            # la fonction a ete desactivee pour favoriser "WindowStaysOnTopHint"
    diag.setWindowFlags(PySide2.QtCore.Qt.WindowStaysOnTopHint)     # PySide2 # cette fonction met la fenetre en avant
    diag.exec_()
        
class Ui_MainWindow(object):

    def __init__(self ):
        self.window = MainWindow
        #self.path  = FreeCAD.ConfigGet("AppHomePath")
        #self.path  = FreeCAD.ConfigGet("UserAppData")
        #self.path  = "your path"
        param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")# macro path
        self.path = param.GetString("MacroPath","") + "/"                   # macro path
        self.path = self.path.replace("\\","/")
        #print("Path for the icons : " , self.path)

    def setupUi(self, MainWindow):
        self.window = MainWindow

#        section horizontalSlider 
        self.horizontalSlider = PySide2.QtWidgets.QSlider(MainWindow)                       # create horizontalSlider
        self.horizontalSlider.setGeometry(QtCore.QRect(10, 10, 400, 16))                    # coordinates position
        self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)                          # orientation Horizontal
#        self.horizontalSlider.setMinimum(-10000.0)                                         # minimum value
        self.horizontalSlider.setMaximum(100000.0)                                           # maximum value
#        self.horizontalSlider.setSingleStep(0.1)                                           # 
#        self.horizontalSlider.setTickInterval(0.1)                                         # 
        self.horizontalSlider.setInvertedAppearance(False)                                  # displacement rigth to left or left to rigth value "True" or "False"
        self.horizontalSlider.setObjectName("horizontalSlider")                             # object Name
        self.horizontalSlider.valueChanged.connect(self.on_horizontal_slider)               # connect on "def on_horizontal_slider:" for execute action

        MainWindow.setWindowTitle(QtWidgets.QApplication.translate("MainWindow", __title__+" ("+__version__+", "+__date__+")"))
        MainWindow.setWindowFlags(PySide2.QtCore.Qt.WindowStaysOnTopHint)        # PySide2 cette fonction met la fenetre en avant
#______________________________________________________________________________________
    def on_horizontal_slider(self, value):
        global camera
        value = value
#        value = -value
#        value = value/100#
#        value = -(value/1000)#
        print(value)
        ##### for first Subobject selected
        #sel = Gui.Selection.getSelectionEx()[0].SubObjects[0].BoundBox.Center        # sub element BoundBox coordinates
        #print(sel)
        ##### for first subobject selected

        ##### for first Object selected
        sel = FreeCADGui.Selection.getSelection()[0]
        selb= sel.Shape.BoundBox.Center
        #print(selb)
        ##### for first Object selected

#        #http://web.mit.edu/ivlib/www/iv/cameras.html
#        PerspectiveCamera. A PerspectiveCamera shows you the scene and applies foreshortening to give you a better impression of distance.
#
#        PerspectiveCamera {
#            viewportMapping  ADJUST_CAMERA
#            position         0 0 1
#            orientation      0 0 1  0
#            aspectRatio      1
#            nearDistance     1
#            farDistance      10
#            focalDistance    5
#            heightAngle      0.785398
#        }
#        Gui.activeDocument().activeView().setCamera(' OrthographicCamera { \n viewportMapping ADJUST_CAMERA \n position 0 0 1 \n orientation 0 0 1 0 \n aspectRatio 1 \n nearDistance 1 \n farDistance 100 \n focalDistance 5 \n height ' + str(value) + ' }')
  
        camera=Gui.ActiveDocument.ActiveView.getCameraNode()
#        print(camera)
#        focalDistance=camera.focalDistance.getValue()

#        Position      = 0, 0, 0   # XYZ 
        Position      = selb[0], selb[1], selb[2]   # XYZ 
        Orientation   = 0, 0, -1, 0
        AspectRatio   = 1
        NearDistance  = 1
        FarDistance   = 10
        FocalDistance = 5
        Height        = value
#        HeightAngle   = value

        #https://forum.freecadweb.org/viewtopic.php?f=22&t=10157
        camera.position.setValue(Position)
        camera.orientation.setValue(Orientation)
        camera.aspectRatio.setValue(AspectRatio)
        camera.nearDistance.setValue(NearDistance)
        camera.farDistance.setValue(FarDistance)
        camera.focalDistance.setValue(FocalDistance)
        camera.height.setValue(Height)
#        camera.heightAngle.setValue(HeightAngle)

#        print(position)

    def on_PB_Quit_clicked(self):
        self.window.hide()                                                  # hide the window and close the macro
        print("Quit ")


#print(Gui.activeDocument().activeView().getCamera())
doc = FreeCAD.ActiveDocument
if doc == None:
    doc = FreeCAD.newDocument()

MainWindow = QtWidgets.QWidget()    #PySide2
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()

#https://forum.freecadweb.org/viewtopic.php?f=22&t=5576&start=10#p96188
#https://forum.freecadweb.org/viewtopic.php?t=26215#p207714
#how to change the distance of the camera?import Part



##http://web.mit.edu/ivlib/www/iv/cameras.html
##https://forum.freecadweb.org/viewtopic.php?f=22&t=6745
#
#"""
#
#    PerspectiveCamera. A PerspectiveCamera shows you the scene and applies foreshortening to give you a better impression of distance.
#
#        PerspectiveCamera {
#            viewportMapping  ADJUST_CAMERA
#            position         0 0 1
#            orientation      0 0 1  0
#            aspectRatio      1
#            nearDistance     1
#            farDistance      10
#            focalDistance    5
#            heightAngle      0.785398
#        }
#
#    OrthographicCamera. A OrthographicCamera shows you the scene but doesn't apply any foreshortening.
#
#        OrthographicCamera {
#            viewportMapping  ADJUST_CAMERA
#            position         0 0 1
#            orientation      0 0 1  0
#            aspectRatio      1
#            nearDistance     1
#            farDistance      10
#            focalDistance    5
#            height           2
#        }
#"""
#
#Gui.activeDocument().activeView().setCamera('#Inventor V2.1 ascii \n OrthographicCamera { \n viewportMapping ADJUST_CAMERA \n position 0 0 87 \n orientation 0 0 1 0 \n nearDistance 37 \n farDistance 137 \n aspectRatio 1 \n focalDistance 87 \n height 119 }')
#



##https://www.forum.freecadweb.org/viewtopic.php?f=22&t=26391
##How to apply Near and Far clipping from a script?
##https://forum.freecadweb.org/viewtopic.php?f=22&t=40938
##Set camera view to sketch center
##https://forum.freecadweb.org/viewtopic.php?t=24788
##Sketch enter Edit Mode by Python Script
#
#try:
#    view=Gui.ActiveDocument.ActiveView
#    view.fitAll()
#    
#    from pivy import coin
#    sel0 = Gui.Selection.getSelection()
##    Gui.Selection.addSelection(App.ActiveDocument.getObject(sel0[0].Name))
#    b = sel0[0].Shape.BoundBox
#    
#    box=coin.SbBox3f()
#    box.setBounds(b.XMin,b.YMin,b.ZMin,b.XMax,b.YMax,b.ZMax)
#
#    cam=view.getCameraNode()
#    cam.nearDistance.getValue()
#    cam.farDistance.getValue() # far distance is quite high
#    cam.focalDistance.getValue()
#    
#    cam.viewBoundingBox(box,1,1) # focuses on the cylinder
#    
#    Gui.ActiveDocument.setEdit(Gui.Selection.getSelectionEx()[0].Object)    # Edit the Object
#except Exception:
#    print("Error")

#from pivy import coin
#camera=Gui.activeDocument().activeView().getCameraNode()
#print(camera)
#camera.height.setValue(min(150, 150))


###https://forum.freecadweb.org/viewtopic.php?t=37841#p321922
##cam = Gui.ActiveDocument.ActiveView.getCamera() #store camera settings to 'cam'
##Gui.ActiveDocument.ActiveView.setCamera(cam) #restore previously stored camera settings

##https://forum.freecadweb.org/viewtopic.php?f=22&t=5576&start=10
##How can you zoom in and out of a document via scripting?

##https://forum.freecadweb.org/viewtopic.php?t=26215#p207714
##how to change the distance of the camera?import Part
#from FreeCAD import Base
#from pivy import coin


#Gui.activeDocument().activeView().setCameraType("Perspective")
#camera = FreeCADGui.ActiveDocument.ActiveView.getCameraNode()
#
#center=coin.SbVec3f(0,0,0)
#orient=camera.orientation.getValue()
#viewdir=coin.SbVec3f(0,0,-1)
#viewdir=orient.multVec(viewdir)
#fd=100
#camera.focalDistance.setValue(fd)
##focalDistance=camera.focalDistance.getValue()
#position=center-viewdir*fd
#camera.position.setValue(position)


sorry
mario
Maybe you need a special feature, go into Macros_recipes and Code_snippets, Topological_data_scripting.
My macros on Gist.github here complete macros Wiki and forum.
Post Reply