6969mesh_scale_factor = 1.0
7070mesh_origin = [0.0 ,0.0 ,0.0 ]
7171
72+ # vertical exaggeration factor
73+ vertical_exaggeration = None
74+
7275## sea-level plane
7376use_sea_level_plane = True
7477
7578## transparent sea-level plane
7679use_transparent_sea_level_plane = False
7780
81+ # shallow coast lines can lead to z-buffering issues with the sea-level plane.
82+ # as a work-around, one can try to add a boolean modifier to cut the plane with the main mesh object.
83+ # this might however lead to other issues... left here to give a try.
84+ add_sea_level_plane_modifier = False
85+
86+ # shifts point above/below sea-level slightly up/down to get a sharper and steeper coastline for sea-level plane
87+ sea_level_separation = None
88+
7889# baseline shift for buildings (to move above SPECFEM mesh)
7990shift_building_baseline = 0.0 # 0.0==no-shift default, or e.g. --shift-building-baseline=0.0005
8091
92+ # location labels (white or black)
93+ location_labels_color = (0.05 ,0.05 ,0.05 ,1 ) # white (0.9,0.9,0.9,1), black (0.05,0.05,0.05,1)
94+
8195# rendering output
8296suppress_renderer_output = False
8397
@@ -486,6 +500,40 @@ def setup_color_table(colormap, data_min, data_max):
486500 [0.5 , 0.0 , 0.0 ], # X+ : darkred
487501 ]
488502
503+ elif colormap == 14 :
504+ # custom shakeUSGSblack
505+ # starts with darker gray than the default USGS
506+ print (" color map: shakeUSGSblack" )
507+ colors_rgb = [
508+ [0.15 , 0.15 , 0.15 ], # black
509+ [0.3 , 0.3 , 0.35 ],
510+ [0.77 , 0.81 , 1.0 ], # II-III : light purple
511+ [0.5 , 1.0 , 0.98 ], # IV: turquoise
512+ [0.5 , 1.0 , 0.54 ], # V : green
513+ [1.0 , 0.98 , 0.0 ], # VI : yellow
514+ [1.0 , 0.77 , 0.0 ], # VII : orange
515+ [0.99 , 0.52 , 0.0 ], # VIII: darkorange
516+ [0.98 , 0.0 , 0.0 ], # IX : red
517+ [0.5 , 0.0 , 0.0 ], # X+ : darkred
518+ ]
519+
520+ elif colormap == 15 :
521+ # custom shake
522+ # starts with dark colors than more light
523+ print (" color map: shakeDark" )
524+ colors_rgb = [
525+ [0.15 , 0.15 , 0.15 ], # black
526+ [0.3 , 0.3 , 0.35 ], #
527+ [0.5 , 0.5 , 0.7 ], # II-III
528+ [0.75 , 0.75 , 0.75 ], # IV
529+ [1.0 , 1.0 , 1.0 ], # V white
530+ [1.0 , 0.98 , 0.0 ], # VI yellow
531+ [1.0 , 0.77 , 0.0 ], # VII orange
532+ [0.99 , 0.52 , 0.0 ], # VIII darkorange
533+ [0.98 , 0.0 , 0.0 ], # IX red
534+ [0.7 , 0.0 , 0.0 ], # X+ darkred
535+ ]
536+
489537 else :
490538 print ("Warning: colormap with type {} is not supported, exiting..." .format (colormap ))
491539 sys .exit (1 )
@@ -513,6 +561,7 @@ def setup_color_table(colormap, data_min, data_max):
513561
514562def convert_vtk_to_obj (vtk_file : str = "" , colormap : int = 0 , color_max = None ) -> str :
515563 global mesh_scale_factor ,mesh_origin
564+ global vertical_exaggeration ,sea_level_separation
516565
517566 # Path to your .vtu file
518567 print ("converting vtk file: " ,vtk_file )
@@ -611,15 +660,35 @@ def convert_vtk_to_obj(vtk_file: str="", colormap: int=0, color_max=None) -> str
611660 print (" scale factor :" ,mesh_scale_factor )
612661 print ("" )
613662
663+ if vertical_exaggeration != None :
664+ print (" using vertical exaggeration factor: " ,vertical_exaggeration )
665+ print ("" )
666+
667+ if sea_level_separation != None :
668+ print (" using sea-level separation shift: " ,sea_level_separation )
669+ print ("" )
670+
614671 # creates an array to store scaled points
615672 scaled_points = vtk .vtkPoints ()
616673
617674 # Loop through each point, scale its coordinates, and add it to the new points array
618675 for i in range (num_points ):
619676 # translation by origin
620677 point = np .array (points .GetPoint (i )) - mesh_origin
678+
621679 # uniform scaling
622680 scaled_point = point * mesh_scale_factor
681+
682+ # vertical exaggeration
683+ if vertical_exaggeration != None :
684+ scaled_point [2 ] = scaled_point [2 ] * vertical_exaggeration
685+
686+ # shift points above/below sea-level
687+ if sea_level_separation != None :
688+ # shift points above
689+ if scaled_point [2 ] > 0.0 : scaled_point [2 ] += sea_level_separation
690+ if scaled_point [2 ] < 0.0 : scaled_point [2 ] -= sea_level_separation
691+
623692 # stores updated points
624693 scaled_points .InsertNextPoint (scaled_point )
625694
@@ -1501,7 +1570,7 @@ def add_plane() -> None:
15011570 """
15021571 adds a plane at sea-level
15031572 """
1504- global use_sea_level_plane ,use_transparent_sea_level_plane
1573+ global use_sea_level_plane ,use_transparent_sea_level_plane , add_sea_level_plane_modifier
15051574 global close_up_view
15061575
15071576 # checks if anything to do
@@ -1539,6 +1608,31 @@ def add_plane() -> None:
15391608 else :
15401609 mat .diffuse_color = (0.135 , 0.135 , 0.135 , 1 ) # gray for better contrast
15411610
1611+ # adds the Boolean modifier
1612+ if add_sea_level_plane_modifier :
1613+ print (" adding sea-level plane - modifier using difference" )
1614+ boolean_modifier = plane_object .modifiers .new (name = "Boolean" , type = 'BOOLEAN' )
1615+
1616+ # Set the operation type
1617+ boolean_modifier .operation = 'DIFFERENCE'
1618+
1619+ # Set the operand object if provided
1620+ mesh_object = bpy .data .objects ['output' ]
1621+ if mesh_object :
1622+ boolean_modifier .object = mesh_object
1623+ else :
1624+ print (" Warning: mesh object 'output' not found." )
1625+
1626+ # Set the solver type
1627+ boolean_modifier .solver = 'FAST' # 'FAST' or 'EXACT'
1628+
1629+ # some further optimizations for the exact solver
1630+ if boolean_modifier .solver == 'EXACT' :
1631+ #boolean_modifier.use_self = True # self-intersection
1632+ #boolean_modifier.use_hole_tolerant = True # better results when more tolerant, but slower
1633+ pass
1634+ print (" modifier added" )
1635+
15421636 plane_object .data .materials .append (mat )
15431637
15441638
@@ -1606,7 +1700,8 @@ def add_location_labels(locations_file: str="") -> None:
16061700 """
16071701 adds locations defined in file
16081702 """
1609- global centered_view
1703+ global centered_view ,use_white_location_labels
1704+ global location_labels_color
16101705
16111706 # checks if anything to do
16121707 if len (locations_file ) == 0 : return
@@ -1735,7 +1830,7 @@ def add_location_labels(locations_file: str="") -> None:
17351830 # Set text material
17361831 text_material = bpy .data .materials .new (name = "TextMaterial" )
17371832 text_material .use_nodes = True
1738- text_material .node_tree .nodes ["Principled BSDF" ].inputs ["Base Color" ].default_value = ( 0.05 , 0.05 , 0.05 , 1 )
1833+ text_material .node_tree .nodes ["Principled BSDF" ].inputs ["Base Color" ].default_value = location_labels_color
17391834 text_material .node_tree .nodes ["Principled BSDF" ].inputs ["Alpha" ].default_value = 1 # transparency
17401835 text_material .node_tree .nodes ["Principled BSDF" ].inputs ["Specular" ].default_value = 0 # Reduce shine
17411836 text_material .shadow_method = 'NONE' # Blender 3.x
@@ -2207,10 +2302,10 @@ def plot_with_blender(vtk_file: str="", image_title: str="", colormap: int=0, co
22072302
22082303
22092304def usage () -> None :
2210- print ("usage: ./plot_with_blender.py [--vtk_file=file] [--title=my_mesh_name] [--colormap=val] [--color-max=val]" )
2305+ print ("usage: ./plot_with_blender.py [--vtk_file=file] [--title=my_mesh_name] [--colormap=val] [--color-max=val] [--vertical-exaggeration=val] " )
22112306 print (" [--buildings=file] [--shift-buildings=val]" )
22122307 print (" [--locations=file] [--utm-zone=ZoneNumber]" )
2213- print (" [--no-sea-level] [--transparent-sea-level]" )
2308+ print (" [--no-sea-level] [--transparent-sea-level] [--sea-level-separation=val] " )
22142309 print (" [--centered] [--closeup] [--small] [--anim]" )
22152310 print (" [--with-cycles/--no-cycles] [--suppress]" )
22162311 print (" [--help]" )
@@ -2222,13 +2317,16 @@ def usage() -> None:
22222317 print (" 10==shakeGreen /11==shakeRed /12==shakeUSGS /13==shakeUSGSgray" )
22232318 print (" (default is shakeUSGSgray for shakemaps)" )
22242319 print (" --color-max - fixes maximum value of colormap for moviedata to val, e.g., 1.e-7)" )
2320+ print (" --vertical-exaggeration - factor to scales vertical dimension" )
22252321 print ("" )
22262322 print (" --buildings - mesh file (.ply) with buildings to visualize for the area" )
22272323 print (" --shift-buildings - moves buildings up, e.g., a factor 0.0005 (default is no shift==0.0)" )
22282324 print (" --locations - file with location labels (using a format: #name #lat #lon)" )
2325+ print (" --white-labels - use white text for location labels" )
22292326 print (" --utm_zone - use specified UTM zone number (1-60) with (+) for Northern (-) for Southern hemisphere (e.g., -58)" )
22302327 print (" --no-sea-level - turns off sea-level plane" )
22312328 print (" --transparent-sea-level - turns on transparency for sea-level plane" )
2329+ print (" --sea-level-separation - shift factor to move up/down points at sea-level for better sea-level separation" )
22322330 print ("" )
22332331 print (" --centered - centered camera view (looking from top straight down)" )
22342332 print (" --closeup - sets camera view closer to center of model" )
@@ -2247,6 +2345,8 @@ def usage() -> None:
22472345 image_title = ""
22482346 color_max = None
22492347 colormap = - 1
2348+ vertical_exaggeration = None
2349+ sea_level_separation_shift = None
22502350 buildings_file = ""
22512351 locations_file = ""
22522352 animation = False
@@ -2293,6 +2393,8 @@ def usage() -> None:
22932393 use_sea_level_plane = False
22942394 elif "--transparent-sea-level" in arg :
22952395 use_transparent_sea_level_plane = True
2396+ elif "--sea-level-separation=" in arg :
2397+ sea_level_separation = float (arg .split ('=' )[1 ])
22962398 elif "--vtk_file=" in arg :
22972399 vtk_file = arg .split ('=' )[1 ]
22982400 elif "--background-dark" in arg :
@@ -2303,12 +2405,15 @@ def usage() -> None:
23032405 world_background_color = (0 ,0 ,0 ,1 ) # black world background
23042406 elif "--locations=" in arg :
23052407 locations_file = arg .split ('=' )[1 ]
2408+ elif "--white-labels" in arg :
2409+ location_labels_color = (0.9 ,0.9 ,0.9 ,1 ) # white location labels
23062410 elif "--utm_zone=" in arg :
2307- str_val = arg .split ('=' )[1 ]
2308- utm_zone = int (str_val )
2411+ utm_zone = int (arg .split ('=' )[1 ])
23092412 if abs (utm_zone ) < 1 or utm_zone > 60 :
23102413 print (f"Invalid UTM zone entered: { utm_zone } - Please use zones from +/- [1,60]" )
23112414 sys .exit (1 )
2415+ elif "--vertical-exaggeration=" in arg :
2416+ vertical_exaggeration = float (arg .split ('=' )[1 ])
23122417 elif i >= 8 :
23132418 print ("argument not recognized: " ,arg )
23142419
0 commit comments