Forum

Author Topic: Selection based on bounding box  (Read 1901 times)

outsider

  • Newbie
  • *
  • Posts: 31
    • View Profile
Selection based on bounding box
« on: May 24, 2020, 07:31:25 PM »
Is there any way to select the elements inside a bounding box?

I did a quick search and came up with this post which deletes all points outside bounding box.
https://www.agisoft.com/forum/index.php?topic=9030.0

I would like to select everything inside the bounding box(mainly mesh elements, but could be useful for all other objects as well).

Can anyone point me in the right direction or suggest how to modify that script?

outsider

  • Newbie
  • *
  • Posts: 31
    • View Profile
Re: Selection based on bounding box
« Reply #1 on: May 26, 2020, 12:14:56 AM »
I found a similar solution on the forum from a while back
https://www.agisoft.com/forum/index.php?topic=7898.0

I converted it to MetaShape in case anyone else needs this functionality

Code: [Select]
import Metashape
import math

# Checking compatibility
compatible_major_version = "1.6"
found_major_version = ".".join(Metashape.app.version.split('.')[:2])
if found_major_version != compatible_major_version:
    raise Exception("Incompatible Metashape version: {} != {}".format(found_major_version, compatible_major_version))

from PySide2 import QtCore, QtGui, QtWidgets
from multiprocessing.dummy import Pool as ThreadPool ##

def checkFaceTask(face):
global vertices
face_vertices = [vertices[v] for v in face.vertices]
checkFace(face, face_vertices)

class progressDialog(QtWidgets.QDialog):
def __init__(self, parent):

QtWidgets.QDialog.__init__(self, parent)

self.setWindowTitle("Crop mesh by region")
self.btnQuit = QtWidgets.QPushButton("Quit")
self.btnQuit.setFixedSize(100,50)
self.btnP1 = QtWidgets.QPushButton("Start")
self.btnP1.setFixedSize(100,50)
self.pBar = QtWidgets.QProgressBar()
self.pBar.setTextVisible(False)
self.pBar.setFixedSize(100, 50)

layout = QtWidgets.QGridLayout()   
layout.addWidget(self.pBar, 0, 0)
layout.addWidget(self.btnP1, 0, 1)
layout.addWidget(self.btnQuit, 0, 2)
self.setLayout(layout)
self.move(500, 400)

proc_markers = lambda : self.process()
QtCore.QObject.connect(self.btnP1, QtCore.SIGNAL("clicked()"), proc_markers)
QtCore.QObject.connect(self.btnQuit, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("reject()"))
self.exec()

def isReady(self):
for task in self.tasks:
if (not task.done):
return False
return True

def onReady(self, result):
print("on ready")

self.pBar.setRange(0,1)
self.btnP1.setDisabled(False)
self.btnQuit.setDisabled(False)
app.processEvents()

Metashape.app.update()
print("Script finished.")
#self.close()

def process(self):

global doc, app
global region, vertices
chunk = doc.chunk
region = chunk.region
print("\nScript started...")
self.btnP1.setDisabled(True)
self.btnQuit.setDisabled(True)
self.pBar.setRange(0,0)
app.processEvents()

for i in range(len(chunk.frames)):

chunk.frame = i
frame = chunk.frames[i]
if not frame.model:
continue
vertices = frame.model.vertices
result = ThreadPool().map_async(checkFaceTask, frame.model.faces, callback = self.onReady)
app.processEvents()
frame.model.removeSelection()
app.processEvents()

def checkFace(face, face_vertices):

global region
R = region.rot #Bounding box rotation matrix
C = region.center #Bounding box center vector
size = region.size
remove_vertices = 0

for vertex in face_vertices:

v = vertex.coord
v.size = 3
v_c = v - C
v_r = R.t() * v_c

if abs(v_r.x) > abs(size.x / 2.):
remove_vertices += 1
elif abs(v_r.y) > abs(size.y / 2.):
remove_vertices += 1
elif abs(v_r.z) > abs(size.z / 2.):
remove_vertices += 1
else:
continue

if remove_vertices == 3:
face.selected = True

def main():

global doc
doc =Metashape.app.document

global app
app = QtWidgets.QApplication.instance()
parent = app.activeWindow()

dlg = progressDialog(parent)
   



label = "Custom menu/Crop mesh by bounding box"
Metashape.app.addMenuItem(label, main)