SELECT isohypse or horizontal terrain contour - vertices sharing same Z

Hi, I have imported a terrain modeled from “isohypse” or horizontal terrain contour, and looks fine when smoothed.
BUT I want to see these lines also when the terrain is smoothed.
See screenshot (“isoipse_other” from an other software).
So I need the select these edge all (the one sharing same Z) and only them.
So I can later give them the corrisponding property in render.
Is there a Short way ?
thank you

isoipse_blender.pdf (413 KB)

isoipse_other.pdf (1.26 MB)

Attachments

isoipse.blend.zip (2.19 MB)

we did a script last year to do that
but have to find where I put this thing !

but that would do it all over not over a simple loop!

happy bl

It wolud be great!
I hope you find it.

I did try a boolean operation with a plane (array along the Z axis) , so to say it “draws” the lines again, but the shape is too complex and does not works.
I remeber as well you could do it in render through the “modulo” math node, but I have to find again how it works.

more or less lik this, though is not (yet) perfectly horizontal, don’t know why. see screenshot.
isoipse.pdf (1.69 MB)

BUT still I do need the other method, selectiong corresponding edges, to use it not only in rendering, for instance in opengl preview and other uses.

with nodes it affects only the material and texture

cannot find it right now
but I redid some script for it using Bmesh
now problem is that if you use = values I mean this is so precise you might never find one !

so need to more or less use a range -very small one but at least will find some values close to some Z value

happy bl

try something like this in text editor

at beginning of program set the Z value and delta value

don’t foget this is reading the local vets value so it ahs some plus or minus value compare to origin


 
import bpy
import bmesh



 

zheight = 0.5
delta = 0.1
print ('zheight =',zheight )
print ()
 
def main(context):
 
 
 global zheight , delta
 
 for ob in context.selected_objects:
 
  edbm = False
  if ob.mode == 'EDIT':
   edbm = True
   
  if edbm:
   bm = bmesh.from_edit_mesh(ob.data)
  else:
   bm = bmesh.new()
   bm.from_mesh(ob.data)
   
  for v in bm.verts:
  
   if v.select or not edbm:
    # Translate all verts if object is in object mode,
    # selected verts only if in edit mode.
    
    
    if  ( v.co[2]  >= zheight - delta ) and ( v.co[2]  <= zheight + delta ):
     v.select =True
     print ('v.co[2] =', v.co[2] , ' z - =', zheight - delta , ' z + =', zheight + delta )
#      v.co += v.normal * 0.2
    else:
     v.select = False
   
   
  if not edbm:
   bm.to_mesh(ob.data)
  ob.data.update()


 print ()
 print ('zheight =',zheight )
 print ()


class SimpleOperator(bpy.types.Operator):
 """Tooltip"""
 bl_idname = "object.simple_operator"
 bl_label = "Simple Object Operator"

 @classmethod
 def poll(cls, context):
  return context.object is not None

 def execute(self, context):
  main(context)
  return {'FINISHED'}

##########

def register():
 bpy.utils.register_class(SimpleOperator)
def unregister():
 bpy.utils.unregister_class(SimpleOperator)  
 
 
if __name__ == "__main__":
 register()
 # test call
 bpy.ops.object.simple_operator() 
 
 
 



happy bl

Attachments


Very nice, it works!
Provided that you remember to select everything, because the script does not select, but de-select.
This said, I’ve made an error:
I thought it was enough to select vertices and then, with vertices selected, you switch to edge mode and you set the properties you need.
In my case, as soon as I switch to edge mode, blender select ALL edges and vertices, not only edges connecting selected vertices.
I can’t figure out why.

I’m not very confindent in Python, so could you suggest me where the change the syntax from “select vertices” to “select edges” ?

Thank you again.

problem is that edge are not at same level in Z
can select only with verts at Z value !

run script in object mode
not certain why it does not work in edit mode !

and I tried to go into edges mode
problem is that you might select other edge connected to the selected verts !

happy bl

hi ricky,
In object mode the script works better, even as the workflow is not so straight forward:

  • go in vertices select mode
  • deselect everything
  • go in object mode
  • run the script
  • go back in edit mode
  • switch to select edges with those vertices selected
  • assign the property as needed (edge crease and freestyle)
  • repeat.

It seams we need in the script something to “reset” selection befor running the script,
and it does not work in edit mode, as the program had a hidden “memory” of selected edges.
It seems to be a common issue:

For edges, blender calculates the midpoint, and that stays on the same Z value.
So it might be worth the effort.
I’m not sure if the point is this
“for v in bm.verts:”
so I’ve searched and found this:


witch could lead to this:

import bpy, bmesh
me = bpy.context.object.data
bm = bmesh.new()
bm.from_mesh(me)
EPSILON = 1.0e-5
zheight = 2.5
for vert in bm.verts:
if ( vert.co.z >= zheight - EPSILON ) and ( vert.co.z <= zheight + EPSILON ):
vert.select = True
for edge in bm.edges:
if edge.verts[0].select and edge.verts[1].select:
edge.select = True
bm.to_mesh(me)
bm.free()

problem is that list of edges might
still have to find common verts to these edges !

and don’t remember you can get average height for edge !

will look at it a bit later today

happy bl

there is also the mesh itself
is it very high res so edges length are very short
or low res and very long edges ?

happy bl