2018-10-24 16:30:09 +00:00
import ecto , os , math
2015-11-30 15:53:44 +00:00
from opendm import log
from opendm import io
from opendm import system
from opendm import context
2018-06-10 18:57:16 +00:00
from opendm import mesh
2018-08-08 19:41:08 +00:00
from opendm import gsd
2015-11-30 15:53:44 +00:00
2015-12-10 11:01:41 +00:00
2016-02-26 18:50:12 +00:00
class ODMeshingCell ( ecto . Cell ) :
2015-12-10 11:01:41 +00:00
def declare_params ( self , params ) :
params . declare ( " max_vertex " , ' The maximum vertex count of the output '
2016-02-26 18:50:12 +00:00
' mesh ' , 100000 )
2015-12-10 11:01:41 +00:00
params . declare ( " oct_tree " , ' Oct-tree depth used in the mesh reconstruction, '
2016-02-26 18:50:12 +00:00
' increase to get more vertices, recommended '
' values are 8-12 ' , 9 )
2015-12-10 11:01:41 +00:00
params . declare ( " samples " , ' Number of points per octree node, recommended '
2016-02-26 18:50:12 +00:00
' value: 1.0 ' , 1 )
2018-07-05 23:02:00 +00:00
params . declare ( " point_weight " , " specifies the importance that interpolation of the point samples is given in the formulation of the screened Poisson equation. " , 4 )
params . declare ( " max_concurrency " , ' max threads ' , context . num_cores )
2016-12-11 22:16:11 +00:00
params . declare ( " verbose " , ' print additional messages to console ' , False )
2015-11-30 15:53:44 +00:00
def declare_io ( self , params , inputs , outputs ) :
2015-12-10 11:01:41 +00:00
inputs . declare ( " tree " , " Struct with paths " , [ ] )
2015-11-30 15:53:44 +00:00
inputs . declare ( " args " , " The application arguments. " , { } )
2015-12-10 11:01:41 +00:00
inputs . declare ( " reconstruction " , " Clusters output. list of ODMReconstructions " , [ ] )
outputs . declare ( " reconstruction " , " Clusters output. list of ODMReconstructions " , [ ] )
2015-11-30 15:53:44 +00:00
def process ( self , inputs , outputs ) :
2016-02-26 18:50:12 +00:00
2016-02-29 14:45:00 +00:00
# Benchmarking
start_time = system . now_raw ( )
2016-03-08 18:26:58 +00:00
log . ODM_INFO ( ' Running ODM Meshing Cell ' )
2015-11-30 15:53:44 +00:00
# get inputs
2018-01-26 19:38:26 +00:00
args = inputs . args
tree = inputs . tree
reconstruction = inputs . reconstruction
2015-11-30 15:53:44 +00:00
# define paths and create working directories
2015-12-10 11:01:41 +00:00
system . mkdir_p ( tree . odm_meshing )
2015-11-30 15:53:44 +00:00
2015-12-01 16:52:18 +00:00
# check if we rerun cell or not
2016-03-08 18:26:58 +00:00
rerun_cell = ( args . rerun is not None and
args . rerun == ' odm_meshing ' ) or \
( args . rerun_all ) or \
( args . rerun_from is not None and
' odm_meshing ' in args . rerun_from )
2015-12-10 11:01:41 +00:00
2018-06-27 18:32:49 +00:00
infile = tree . smvs_model
2018-08-11 16:45:21 +00:00
if args . fast_orthophoto :
2018-01-02 17:38:15 +00:00
infile = os . path . join ( tree . opensfm , ' reconstruction.ply ' )
2018-08-11 16:45:21 +00:00
elif args . use_opensfm_dense :
infile = tree . opensfm_model
2017-04-05 17:56:48 +00:00
2018-07-03 16:37:39 +00:00
# Create full 3D model unless --skip-3dmodel is set
if not args . skip_3dmodel :
2018-01-02 17:38:15 +00:00
if not io . file_exists ( tree . odm_mesh ) or rerun_cell :
log . ODM_DEBUG ( ' Writing ODM Mesh file in: %s ' % tree . odm_mesh )
2018-07-06 14:01:33 +00:00
mesh . screened_poisson_reconstruction ( infile ,
2018-07-03 15:24:47 +00:00
tree . odm_mesh ,
2018-07-06 14:01:33 +00:00
depth = self . params . oct_tree ,
samples = self . params . samples ,
maxVertexCount = self . params . max_vertex ,
pointWeight = self . params . point_weight ,
threads = self . params . max_concurrency ,
2018-07-06 14:29:55 +00:00
verbose = self . params . verbose )
2018-07-03 15:24:47 +00:00
2018-01-02 17:38:15 +00:00
else :
log . ODM_WARNING ( ' Found a valid ODM Mesh file in: %s ' %
tree . odm_mesh )
2016-02-26 18:50:12 +00:00
2018-07-03 16:37:39 +00:00
# Always generate a 2.5D mesh
# unless --use-3dmesh is set.
if not args . use_3dmesh :
2017-04-05 17:56:48 +00:00
if not io . file_exists ( tree . odm_25dmesh ) or rerun_cell :
2018-06-10 18:57:16 +00:00
2017-04-05 17:56:48 +00:00
log . ODM_DEBUG ( ' Writing ODM 2.5D Mesh file in: %s ' % tree . odm_25dmesh )
2018-10-17 15:35:18 +00:00
ortho_resolution = gsd . cap_resolution ( args . orthophoto_resolution , tree . opensfm_reconstruction , ignore_gsd = args . ignore_gsd ) / 100.0
2018-10-17 22:54:18 +00:00
dsm_multiplier = max ( 1.0 , gsd . rounded_gsd ( tree . opensfm_reconstruction , default_value = 4 , ndigits = 3 , ignore_gsd = args . ignore_gsd ) )
2018-10-17 15:35:18 +00:00
2018-10-17 22:54:18 +00:00
# A good DSM size depends on the flight altitude.
# Flights at low altitude need more details (higher resolution)
# Flights at higher altitude benefit from smoother surfaces (lower resolution)
dsm_resolution = ortho_resolution * dsm_multiplier
2018-10-24 16:30:09 +00:00
dsm_radius = dsm_resolution * math . sqrt ( 2 )
# Sparse point clouds benefits from using
# a larger radius interolation --> less holes
if args . fast_orthophoto :
dsm_radius * = 2
2018-10-17 22:54:18 +00:00
log . ODM_DEBUG ( ' ODM 2.5D DSM resolution: %s ' % dsm_resolution )
2018-10-28 23:57:08 +00:00
2018-07-06 14:01:33 +00:00
mesh . create_25dmesh ( infile , tree . odm_25dmesh ,
2018-10-17 15:35:18 +00:00
dsm_radius = dsm_radius ,
dsm_resolution = dsm_resolution ,
2018-07-02 19:21:30 +00:00
depth = self . params . oct_tree ,
2018-07-03 15:24:47 +00:00
maxVertexCount = self . params . max_vertex ,
2018-07-07 04:15:15 +00:00
samples = self . params . samples ,
2018-07-03 17:01:18 +00:00
verbose = self . params . verbose ,
2018-12-12 19:24:27 +00:00
available_cores = args . max_concurrency ,
2018-10-28 23:57:08 +00:00
method = ' poisson ' if args . fast_orthophoto else ' gridded ' )
2017-04-05 17:56:48 +00:00
else :
log . ODM_WARNING ( ' Found a valid ODM 2.5D Mesh file in: %s ' %
tree . odm_25dmesh )
2018-01-26 19:38:26 +00:00
outputs . reconstruction = reconstruction
2016-03-08 18:26:58 +00:00
if args . time :
2016-02-29 14:45:00 +00:00
system . benchmark ( start_time , tree . benchmarking , ' Meshing ' )
2016-03-08 18:26:58 +00:00
log . ODM_INFO ( ' Running ODM Meshing Cell - Finished ' )
return ecto . OK if args . end_with != ' odm_meshing ' else ecto . QUIT