def invoke(self, context, event): if(context.active_object): self.subject = context.active_object; self.bm = getBMMesh(context, self.subject, False); self.richmodel = None; if(not isFastAlgorithmLoaded): try: self.richmodel = RichModel(self.bm, self.subject); self.richmodel.Preprocess(); except: print('CANNOT CREATE RICH MODEL'); self.richmodel = None; self.vertex_distances = []; self.alg = ChenhanGeodesics(context, self.subject, self.bm, self.richmodel); self.isolines = []; self.isoorigin = (); self.highlight_point = (0,0,0); self.kd = buildKDTree(context, self.subject, type="VERT"); self.lastkeypress = time.time(); context.scene.objects.active = self.subject; self.subject.select = True; args = (self, context); self._handle = bpy.types.SpaceView3D.draw_handler_add(DrawGL, args, 'WINDOW', 'POST_VIEW'); context.window_manager.modal_handler_add(self); return {'RUNNING_MODAL'}
def getGeodesicAlgorithm(self, context, mesh): richmodel = None bm = getBMMesh(context, mesh, False) alg = None if (not isFastAlgorithmLoaded): try: richmodel = RichModel(bm, mesh) richmodel.Preprocess() except: print('CANNOT CREATE RICH MODEL') richmodel = None #If py_chenhann the c port of geodesics is available then richmodel is not necessary #if py_chenhann is not available and the richmodel is available then proceed to geodesics calculation if (richmodel or isFastAlgorithmLoaded): #Intitialize the chenhan algorithm and fill the K x K matrix of graph paths for minimal spanning tree alg = ChenhanGeodesics(context, mesh, bm, richmodel) bm.free() return alg
class SpecifiedIsoContours(bpy.types.Operator): """Draw a line with the mouse""" bl_idname = "ashok.specifiedisocontours"; bl_label = "Isolines Visualizer"; bl_description = "Given a mesh show isolines" hit = FloatVectorProperty(name="hit", size=3); def getWorldFacePoint(self, context, mesh, face): arr = []; path = [mesh.data.vertices[vindex].co for vindex in face.vertices]; for co in path: arr.append(mesh.matrix_world * co); return arr; def modal(self, context, event): region = context.region; rv3d = context.region_data; obj = context.active_object; context.area.tag_redraw(); # print(event.type, event.value); if(not context.scene.isolinesupdated and self.alg and len(self.vertex_distances)): dist_max = max(self.vertex_distances); n_count = max(self.subject.isolines_count, 1); print('DISTANCE MAX ::: ', dist_max); isolines = GetIsoLines(n_count, self.subject, self.richmodel, self.vertex_distances, useDistance=self.subject.specific_distance_ratio*dist_max); self.constant_points[self.vertex_index] = copy.deepcopy(isolines); for segment in isolines: segment['start'] = self.subject.matrix_world * segment['start']; segment['end'] = self.subject.matrix_world * segment['end']; self.constant_points_transformed[self.vertex_index] = isolines; self.isolines.clear(); for key_vindex in self.constant_points_transformed: self.isolines.extend(self.constant_points_transformed[key_vindex]); print('LEN OF ISOLINES: %s'%(len(self.isolines))); # createIsoContourMesh(context, self.subject, self.isolines); context.scene.isolinesupdated = True; if event.type in {'ESC'}: bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW'); if(self.bm): self.bm.free(); return {'CANCELLED'} if(event.type == 'I' and event.value == 'PRESS'): diffkey = time.time() - self.lastkeypress; if(diffkey > 3): self.lastkeypress = time.time(); if(event.type == "I"): self.hit, onMesh, face_index, hitpoint = ScreenPoint3D(context, event, self.subject, position_mouse = False); if(self.richmodel or isFastAlgorithmLoaded): vco, vindex, dist = self.kd.find(hitpoint); self.alg.addSeedIndex(vindex); self.vertex_distances = self.alg.getVertexDistances(vindex); self.max_godesic_distance = np.amax(self.vertex_distances); self.isoorigin = self.subject.matrix_world * self.subject.data.vertices[vindex].co; self.constant_points[vindex] = []; self.vertex_index = vindex; context.scene.isolinesupdated = False; return {'RUNNING_MODAL'}; elif event.type in {'F'}: bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW'); if(self.bm): self.bm.free(); self.isolines.clear(); for key_vindex in self.constant_points: self.isolines.extend(self.constant_points[key_vindex]); createIsoContourMesh(context, self.subject, self.isolines); return {'FINISHED'}; elif(event.type == 'UP_ARROW' and event.value == 'PRESS'): diffkey = time.time() - self.lastkeypress; if(diffkey > 0.2): self.lastkeypress = time.time(); self.subject.specific_distance_ratio = min(1.0, self.subject.specific_distance_ratio+0.01); return {'RUNNING_MODAL'}; elif(event.type == 'DOWN_ARROW' and event.value == 'PRESS'): diffkey = time.time() - self.lastkeypress; if(diffkey > 0.2): self.lastkeypress = time.time(); self.subject.specific_distance_ratio = max(0.01, self.subject.specific_distance_ratio-0.01); return {'RUNNING_MODAL'}; elif(event.type == 'MOUSEMOVE'): self.hit, onMesh, face_index, hitpoint = ScreenPoint3D(context, event, self.subject, position_mouse = False); if(onMesh): if(face_index): vco, vindex, dist = self.kd.find(hitpoint); self.highlight_point = self.subject.matrix_world * self.subject.data.vertices[vindex].co; context.area.header_text_set("Maximum Geodesic Distance: %f"%(self.max_godesic_distance)); return {'PASS_THROUGH'}; def invoke(self, context, event): if(context.active_object): self.subject = context.active_object; self.bm = getBMMesh(context, self.subject, False); self.richmodel = None; if(not isFastAlgorithmLoaded): try: self.richmodel = RichModel(self.bm, self.subject); self.richmodel.Preprocess(); except: print('CANNOT CREATE RICH MODEL'); self.richmodel = None; self.vertex_distances = []; self.max_godesic_distance = 0.0; self.alg = ChenhanGeodesics(context, self.subject, self.bm, self.richmodel); self.isolines = []; self.constant_points = {}; self.constant_points_transformed = {}; self.vertex_index = 0; self.isoorigin = (); self.highlight_point = (0,0,0); self.kd = buildKDTree(context, self.subject, type="VERT"); self.lastkeypress = time.time(); context.scene.objects.active = self.subject; self.subject.select = True; args = (self, context); self._handle = bpy.types.SpaceView3D.draw_handler_add(DrawGL, args, 'WINDOW', 'POST_VIEW'); context.window_manager.modal_handler_add(self); return {'RUNNING_MODAL'}
class IsoContours(bpy.types.Operator): """Draw a line with the mouse""" bl_idname = "ashok.isocontours"; bl_label = "Isolines Visualizer"; bl_description = "Given a mesh show isolines" hit = FloatVectorProperty(name="hit", size=3); def getWorldFacePoint(self, context, mesh, face): arr = []; path = [mesh.data.vertices[vindex].co for vindex in face.vertices]; for co in path: arr.append(mesh.matrix_world * co); return arr; # def saveIsoContoursMesh(self, context): def modal(self, context, event): region = context.region; rv3d = context.region_data; obj = context.active_object; context.area.tag_redraw(); if(not context.scene.isolinesupdated and self.alg and len(self.vertex_distances)): self.isolines = GetIsoLines(self.subject.isolines_count+1, self.subject, self.richmodel, self.vertex_distances); # self.isolines = self.alg.GetIsoLines(self.subject.isolines_count+1); createIsoContourMesh(context, self.subject, self.isolines); for segment in self.isolines: segment['start'] = self.subject.matrix_world * segment['start']; segment['end'] = self.subject.matrix_world * segment['end']; context.scene.isolinesupdated = True; if event.type in {'ESC'}: bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW'); if(self.bm): self.bm.free(); return {'CANCELLED'} elif(event.type == 'I' and event.value == 'PRESS'): diffkey = time.time() - self.lastkeypress; if(diffkey > 3): self.lastkeypress = time.time(); if(event.type == "I"): self.hit, onMesh, face_index, hitpoint = ScreenPoint3D(context, event, self.subject, position_mouse = False); if(self.richmodel or isFastAlgorithmLoaded): vco, vindex, dist = self.kd.find(hitpoint); self.alg.addSeedIndex(vindex); self.vertex_distances = self.alg.getVertexDistances(vindex); self.isoorigin = self.subject.matrix_world * self.subject.data.vertices[vindex].co; context.scene.isolinesupdated = False; return {'RUNNING_MODAL'}; elif(event.type == 'MOUSEMOVE'): self.hit, onMesh, face_index, hitpoint = ScreenPoint3D(context, event, self.subject, position_mouse = False); if(onMesh): if(face_index): vco, vindex, dist = self.kd.find(hitpoint); self.highlight_point = self.subject.matrix_world * self.subject.data.vertices[vindex].co; return {'PASS_THROUGH'}; def invoke(self, context, event): if(context.active_object): self.subject = context.active_object; self.bm = getBMMesh(context, self.subject, False); self.richmodel = None; if(not isFastAlgorithmLoaded): try: self.richmodel = RichModel(self.bm, self.subject); self.richmodel.Preprocess(); except: print('CANNOT CREATE RICH MODEL'); self.richmodel = None; self.vertex_distances = []; self.alg = ChenhanGeodesics(context, self.subject, self.bm, self.richmodel); self.isolines = []; self.isoorigin = (); self.highlight_point = (0,0,0); self.kd = buildKDTree(context, self.subject, type="VERT"); self.lastkeypress = time.time(); context.scene.objects.active = self.subject; self.subject.select = True; args = (self, context); self._handle = bpy.types.SpaceView3D.draw_handler_add(DrawGL, args, 'WINDOW', 'POST_VIEW'); context.window_manager.modal_handler_add(self); return {'RUNNING_MODAL'}
def GetIsoLines(num, meshobject, model = None, vertex_distances= [], *, useDistance = -1.0, contour_index=-1, contour_point=None): print('THE SIZE OF GIVEN VERTEX DISTANCES :::: ', len(vertex_distances)); if(not model): model = RichModel(getBMMesh(bpy.context, meshobject, useeditmode=False), meshobject); model.Preprocess(); farestDis = 0.0; isolines = []; if(useDistance < 0.0): for distance in vertex_distances: farestDis = max(farestDis, distance); else: farestDis = useDistance; gap = farestDis / float(num); points = []; for i in range(model.GetNumOfFaces()): high, middle, low, total = 0,0,0,0; highestDis = -Constants.FLT_MAX; lowestDis = Constants.FLT_MAX; fBadFace = False; for j in range(3): if (vertex_distances[model.Face(i).verts[j]] > (10000.0 / model.m_scale)): fBadFace = True; break; #Find the highest distance if (vertex_distances[model.Face(i).verts[j]] > highestDis): high = model.Face(i).verts[j]; highestDis = vertex_distances[model.Face(i).verts[j]]; if (vertex_distances[model.Face(i).verts[j]] < lowestDis): low = model.Face(i).verts[j]; lowestDis = vertex_distances[model.Face(i).verts[j]]; total += model.Face(i).verts[j]; if(fBadFace): continue; if(high == low): continue; middle = total - high - low; ptLow = model.ComputeShiftPoint(low); ptMiddle = model.ComputeShiftPoint(middle); ptHigh = model.ComputeShiftPoint(high); for j in range(int(vertex_distances[low] / gap) + 1, int(vertex_distances[middle] / gap)+1): segment = {}; dis = gap * j; #Ensure that lines plotted are always below the requested farthest distance if(useDistance != -1.0 and dis > farestDis): continue; prop = (dis - vertex_distances[low]) / (vertex_distances[middle] - vertex_distances[low]); pt = CombineTwoNormalsTo(ptLow, 1 - prop, ptMiddle, prop); segment['start'] = pt * model.m_scale; prop = (dis - vertex_distances[low]) / (vertex_distances[high] - vertex_distances[low]); pt = CombineTwoNormalsTo(ptLow, 1 - prop, ptHigh, prop); segment['end'] = pt * model.m_scale; segment['contour_point'] = contour_point; if(contour_index == -1): segment['contour_index'] = j; else: segment['contour_index'] = contour_index; isolines.append(segment); points.append(segment['start']); for j in range(int(vertex_distances[middle] / gap) + 1, int(vertex_distances[high] / gap)+1): segment = {}; dis = gap * j; #Ensure that lines plotted are always below the requested farthest distance if(useDistance != -1.0 and dis > farestDis): continue; prop = (dis - vertex_distances[middle]) / (vertex_distances[high] - vertex_distances[middle]); pt = CombineTwoNormalsTo(ptMiddle, 1 - prop, ptHigh, prop); segment['start'] = pt * model.m_scale; prop = (dis - vertex_distances[low]) / (vertex_distances[high] - vertex_distances[low]); pt = CombineTwoNormalsTo(ptLow, 1 - prop, ptHigh, prop); segment['end'] = pt * model.m_scale; segment['contour_point'] = contour_point; if(contour_index == -1): segment['contour_index'] = j; else: segment['contour_index'] = contour_index; isolines.append(segment); points.append(segment['start']); return isolines;
class ChenhanGeodesicsOperator(bpy.types.Operator): """Draw a line with the mouse""" bl_idname = "ashok.geodesics_chenhan" bl_label = "Geodesics using ChenHan's algorithm" hit = FloatVectorProperty(name="hit", size=3) algorithm_counter = 0 def applyMarkerColor(self, object): try: material = bpy.data.materials[object.name + '_MouseMarkerMaterial'] except: material = bpy.data.materials.new(object.name + '_MouseMarkerMaterial') material.diffuse_color = (1.0, 0.0, 0.0) material.alpha = 1 material.specular_color = (1.0, 0.0, 0.0) object.data.materials.clear() object.data.materials.append(material) def getSequencedShortestPath(self, v1, v2, local_path=False): path = None reflected_path = None if (v1 != v2): path, reflected_path = self.chenhan.path_between( v1, v2, local_path=local_path) return path, reflected_path def endOperator(self, context): context.area.header_text_set() bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') if (self.bm): self.bm.free() def modal(self, context, event): region = context.region rv3d = context.region_data obj = context.active_object context.area.tag_redraw() #======================================================================= # print('EVENT ::: ', event.type, event.value); #======================================================================= if event.type in {'ESC'}: print('INDICES :: ', self.chenhan.m_seed_indices) self.endOperator(context) return {'CANCELLED'} elif (event.value == 'PRESS' and event.type == 'A'): diffmouse = time.time() - self.lastmousepress if (diffmouse > Constants.TIME_INTERVAL_MOUSE_PRESS): self.lastmousepress = time.time() else: return {'RUNNING_MODAL'} if (len(self.reflected_paths)): createGeodesicPathMesh(context, self.mesh, self.for_reflected_paths_as_mesh, suffix='reflectedpaths') if (len(self.paths)): createGeodesicPathMesh(context, self.mesh, self.for_paths_as_mesh, suffix='geodesicpaths') self.endOperator(context) return {'FINISHED'} 1 return {'RUNNING_MODAL'} elif (event.value == "PRESS" and event.type == "LEFTMOUSE"): if (self.pausedrawing): return {'PASS_THROUGH'} self.hit, onMesh, face_index, hitpoint = ScreenPoint3D( context, event) if (onMesh): diffmouse = time.time() - self.lastmousepress if (diffmouse > Constants.TIME_INTERVAL_MOUSE_PRESS): self.lastmousepress = time.time() else: return {'RUNNING_MODAL'} find_co, index, dist = self.kdtree.find(hitpoint) if (len(self.chenhan.getSeedIndices()) > 0): if (self.chenhan.getSeedIndices()[-1] == index): return {'PASS_THROUGH'} self.chenhan.addSeedIndex(index) print('ADDED SEED INDEX ', index) self.currentseed = index stable_paths = [{ 'start': -1, 'end': -1, 'points': None }] if (len(self.chenhan.getSeedIndices()) > 1): p_indices = self.chenhan.getSeedIndices() stable_paths, stable_reflected_paths = self.getSequencedShortestPath( p_indices[-2], p_indices[-1]) if (stable_paths): stable_paths_for_mesh, stable_reflected_paths_for_mesh = self.getSequencedShortestPath( p_indices[-2], p_indices[-1], local_path=True) self.paths.append(stable_paths) self.for_paths_as_mesh.append(stable_paths_for_mesh) if (len(stable_reflected_paths)): self.reflected_paths.append(stable_reflected_paths) self.for_reflected_paths_as_mesh.append( stable_reflected_paths_for_mesh) return {'PASS_THROUGH'} elif event.type == 'MOUSEMOVE': if (self.pausedrawing): return {'PASS_THROUGH'} self.hit, onMesh, face_index, hitpoint = ScreenPoint3D( context, event) if (onMesh): find_co, index, dist = self.kdtree.find(hitpoint) if (len(self.chenhan.getSeedIndices()) > 0): obj = self.mesh p_indices = self.chenhan.getSeedIndices() currentseed = index temp_paths, temp_reflected_paths = self.getSequencedShortestPath( p_indices[-1], currentseed) try: del self.temppath3d[0] del self.reflected_temppath3d[0] except IndexError: pass if (temp_paths): self.temppath3d.append(temp_paths) self.reflected_temppath3d.append(temp_reflected_paths) context.area.header_text_set("hit: %.4f %.4f %.4f" % tuple(self.hit)) return {'PASS_THROUGH'} return {'PASS_THROUGH'} def startModalOperations(self, context): self.pausedrawing = False self.lastkeypress = time.time() self.lastmousepress = time.time() self.mesh = context.active_object self.bm = getBMMesh(context, self.mesh, False) maxsize = max(self.mesh.dimensions.x, self.mesh.dimensions.y, self.mesh.dimensions.z) markersize = maxsize * 0.01 tempmarkersource = "GeodesicMarker" try: tempmarker = bpy.data.objects[tempmarkersource] except KeyError: bpy.ops.mesh.primitive_uv_sphere_add(segments=36, ring_count=36) tempmarker = context.object tempmarker.name = "GeodesicMarker" tempmarker.dimensions = (markersize, markersize, markersize) # self.mousepointer = getDuplicatedObject(context, tempmarker, "MouseMarker"); self.mousepointer = tempmarker self.applyMarkerColor(self.mousepointer) # self.mousepointer = getDuplicatedObject(context, tempmarker, "MouseMarker"); self.mousepointer.hide = False self.mousepointer.hide_select = False self.mousepointer.show_wire = False self.mousepointer.show_all_edges = False bpy.ops.object.select_all(action="DESELECT") self.mesh.select = False context.scene.objects.active = self.mesh self.richmodel = None self.reflectormesh = None if (not isFastAlgorithmLoaded): self.richmodel = RichModel(self.bm, context.active_object) self.richmodel.Preprocess() if (self.mesh.reflectormesh != 'None'): temp_reflectormesh = context.scene.objects[self.mesh.reflectormesh] r_verts = temp_reflectormesh.data.vertices r_faces = temp_reflectormesh.data.polygons r_edges = temp_reflectormesh.data.edges m_verts = self.mesh.data.vertices m_faces = self.mesh.data.polygons m_edges = self.mesh.data.edges if (len(r_verts) == len(m_verts) and len(r_faces) == len(m_faces) and len(r_edges) == len(m_edges)): self.reflectormesh = context.scene.objects[ self.mesh.reflectormesh] print('REFLECTOR MESH :::: ', self.mesh.reflectormesh, self.mesh.reflectormesh is None) #self.chenhan = ChenhanGeodesics(context, context.active_object, self.bm, self.richmodel); self.chenhan = AnisotropicGeodesics(context, context.active_object, self.bm, self.richmodel, self.reflectormesh) if (isFastAlgorithmLoaded()): self.richmodel = self.chenhan.getRichModel() self.paths = [] self.reflected_paths = [] self.for_paths_as_mesh = [] self.for_reflected_paths_as_mesh = [] self.prev = {} self.temppath3d = [] self.reflected_temppath3d = [] self.seeds = [] self.currentseed = 0 self.currentseed_quad = 0 self.kdtree = buildKDTree(context, self.mesh) args = (self, context, self.paths, self.temppath3d, self.reflected_paths, self.reflected_temppath3d, (0.0, 1.0, 0.0, 1.0), 5.0) self._handle = bpy.types.SpaceView3D.draw_handler_add( DrawGLLines, args, 'WINDOW', 'POST_VIEW') context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'} def invoke(self, context, event): print('INVOKE MODALITY') return self.startModalOperations(context) def execute(self, context): print('EXECUTE MODALITY') return self.startModalOperations(context)
def startModalOperations(self, context): self.pausedrawing = False self.lastkeypress = time.time() self.lastmousepress = time.time() self.mesh = context.active_object self.bm = getBMMesh(context, self.mesh, False) maxsize = max(self.mesh.dimensions.x, self.mesh.dimensions.y, self.mesh.dimensions.z) markersize = maxsize * 0.01 tempmarkersource = "GeodesicMarker" try: tempmarker = bpy.data.objects[tempmarkersource] except KeyError: bpy.ops.mesh.primitive_uv_sphere_add(segments=36, ring_count=36) tempmarker = context.object tempmarker.name = "GeodesicMarker" tempmarker.dimensions = (markersize, markersize, markersize) # self.mousepointer = getDuplicatedObject(context, tempmarker, "MouseMarker"); self.mousepointer = tempmarker self.applyMarkerColor(self.mousepointer) # self.mousepointer = getDuplicatedObject(context, tempmarker, "MouseMarker"); self.mousepointer.hide = False self.mousepointer.hide_select = False self.mousepointer.show_wire = False self.mousepointer.show_all_edges = False bpy.ops.object.select_all(action="DESELECT") self.mesh.select = False context.scene.objects.active = self.mesh self.richmodel = None self.reflectormesh = None if (not isFastAlgorithmLoaded): self.richmodel = RichModel(self.bm, context.active_object) self.richmodel.Preprocess() if (self.mesh.reflectormesh != 'None'): temp_reflectormesh = context.scene.objects[self.mesh.reflectormesh] r_verts = temp_reflectormesh.data.vertices r_faces = temp_reflectormesh.data.polygons r_edges = temp_reflectormesh.data.edges m_verts = self.mesh.data.vertices m_faces = self.mesh.data.polygons m_edges = self.mesh.data.edges if (len(r_verts) == len(m_verts) and len(r_faces) == len(m_faces) and len(r_edges) == len(m_edges)): self.reflectormesh = context.scene.objects[ self.mesh.reflectormesh] print('REFLECTOR MESH :::: ', self.mesh.reflectormesh, self.mesh.reflectormesh is None) #self.chenhan = ChenhanGeodesics(context, context.active_object, self.bm, self.richmodel); self.chenhan = AnisotropicGeodesics(context, context.active_object, self.bm, self.richmodel, self.reflectormesh) if (isFastAlgorithmLoaded()): self.richmodel = self.chenhan.getRichModel() self.paths = [] self.reflected_paths = [] self.for_paths_as_mesh = [] self.for_reflected_paths_as_mesh = [] self.prev = {} self.temppath3d = [] self.reflected_temppath3d = [] self.seeds = [] self.currentseed = 0 self.currentseed_quad = 0 self.kdtree = buildKDTree(context, self.mesh) args = (self, context, self.paths, self.temppath3d, self.reflected_paths, self.reflected_temppath3d, (0.0, 1.0, 0.0, 1.0), 5.0) self._handle = bpy.types.SpaceView3D.draw_handler_add( DrawGLLines, args, 'WINDOW', 'POST_VIEW') context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'}