Skip to content

Commit e198f69

Browse files
committed
corrected map generation in dataframe panel to take n_points into account
1 parent 327583f commit e198f69

9 files changed

Lines changed: 608 additions & 108 deletions

File tree

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
import numpy as np
12
import openalea.mesh
23

34
from openalea.mesh import PropertyTopomesh
45
from openalea.mesh.property_topomesh_io import read_ply_property_topomesh
5-
from openalea.mesh.property_topomesh_analysis import compute_topomesh_property
6+
from openalea.mesh.property_topomesh_analysis import compute_topomesh_property, compute_topomesh_vertex_property_from_faces
7+
from openalea.mesh.triangular_mesh import topomesh_to_triangular_mesh
8+
9+
from openalea.container import array_dict
10+
611

712
from openalea.deploy.shared_data import shared_data
813
dirname = shared_data(openalea.mesh)
@@ -11,31 +16,10 @@
1116
topomesh = read_ply_property_topomesh(filename)
1217
world.add(topomesh, "topomesh")
1318

14-
import numpy as np
15-
from openalea.cellcomplex.property_topomesh.triangular_mesh import topomesh_to_triangular_mesh
16-
from openalea.container import array_dict
17-
18-
compute_topomesh_property(topomesh,'epidermis',1)
19-
compute_topomesh_property(topomesh,'cells',1)
20-
21-
edge_n_cells = np.array(map(len,topomesh.wisp_property('cells',1).values()))
22-
edge_is_cell_edge = edge_n_cells>2
23-
edge_is_cell_edge = edge_is_cell_edge | (edge_n_cells>1)&(topomesh.wisp_property('epidermis',1).values())
24-
25-
edge_is_cell_edge = array_dict(edge_is_cell_edge,list(topomesh.wisps(1)))
26-
27-
mesh,_ = topomesh_to_triangular_mesh(topomesh,1)
28-
29-
edges_to_remove = []
30-
for eid in mesh.edges:
31-
if not edge_is_cell_edge[eid]:
32-
edges_to_remove += [eid]
33-
for eid in edges_to_remove:
34-
del mesh.edges[eid]
35-
if mesh.edge_data.has_key(eid):
36-
del mesh.edge_data[eid]
37-
38-
world.add(mesh)
19+
compute_topomesh_property(topomesh,'normal',2,normal_method='orientation')
20+
compute_topomesh_vertex_property_from_faces(topomesh,'normal',neighborhood=3,adjacency_sigma=1.2)
21+
compute_topomesh_property(topomesh,'mean_curvature',2)
22+
compute_topomesh_vertex_property_from_faces(topomesh,'mean_curvature',neighborhood=3,adjacency_sigma=1.2)
3923

4024

4125

src/openalea/cellcomplex/gmap/basicshapes.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ def topopolyline(nbpoints = 3, gmap = None):
2020
gmap.link_darts(1, darts[2*i+1], darts[2*i+2])
2121
return gmap, darts
2222

23-
2423
def toposquare(gmap = None):
2524
return topopolygon(4,gmap)
2625

src/openalea/cellcomplex/mesh_oalab/widget/dataframe_panel.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ def update_dataframe_figure(self, world_object, attribute):
494494
elif world_object['plot'] == 'map':
495495
data_range = [[X.min()-0.5*(X.max()-X.min()),X.max()+0.5*(X.max()-X.min())],[Y.min()-0.5*(Y.max()-Y.min()),Y.max()+0.5*(Y.max()-Y.min())]]
496496
# print mpl_norm(labels)
497-
map_plot(figure,X,Y,mpl_norm(labels),mpl_cmap,data_range,xlabel=xlabel,ylabel=ylabel,smooth_factor=smooth*10,linewidth=linewidth,alpha=alpha)
497+
map_plot(figure,X,Y,mpl_norm(labels),mpl_cmap,data_range,xlabel=xlabel,ylabel=ylabel,smooth_factor=smooth*10,n_points=10.*world_object['n_points'],linewidth=linewidth,alpha=alpha)
498498

499499

500500

src/openalea/cellcomplex/property_topomesh/property_topomesh_analysis.py

Lines changed: 62 additions & 23 deletions
Large diffs are not rendered by default.

src/openalea/cellcomplex/property_topomesh/property_topomesh_extraction.py

Lines changed: 352 additions & 15 deletions
Large diffs are not rendered by default.

src/openalea/cellcomplex/property_topomesh/property_topomesh_io.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ def save_ply_cellcomplex_topomesh(topomesh,ply_filename,color_faces=False,colorm
306306
print "<-- Saving .ply [",end_time-start_time,"s]"
307307

308308

309-
def save_ply_property_topomesh(topomesh,ply_filename,properties_to_save=dict([(0,[]),(1,['length']),(2,['area','epidermis']),(3,[])]),color_faces=False, coordinatepropname = 'barycenter', verbose = True):
309+
def save_ply_property_topomesh(topomesh,ply_filename,properties_to_save=dict([(0,[]),(1,['length']),(2,['area','epidermis']),(3,[])]),color_faces=False, colormap=None, coordinatepropname='barycenter', verbose=True):
310310
if verbose:
311311
start_time =time()
312312
print "--> Saving .ply"
@@ -384,9 +384,18 @@ def save_ply_property_topomesh(topomesh,ply_filename,properties_to_save=dict([(0
384384
# for eid in topomesh.borders(2,fid):
385385
# ply_file.write(str(edge_index[eid])+" ")
386386
if color_faces:
387-
ply_file.write(str(triangle_data[fid])+" ")
388-
ply_file.write(str(triangle_data[fid])+" ")
389-
ply_file.write(str(triangle_data[fid])+" ")
387+
# ply_file.write(str(triangle_data[fid])+" ")
388+
# ply_file.write(str(triangle_data[fid])+" ")
389+
# ply_file.write(str(triangle_data[fid])+" ")
390+
if colormap is None:
391+
ply_file.write(str(triangle_data[fid])+" ")
392+
ply_file.write(str(triangle_data[fid])+" ")
393+
ply_file.write(str(triangle_data[fid])+" ")
394+
else:
395+
color = colormap._color_points.values()[int(triangle_data[fid])]
396+
ply_file.write(str(int(255*color[0]))+" ")
397+
ply_file.write(str(int(255*color[1]))+" ")
398+
ply_file.write(str(int(255*color[2]))+" ")
390399
for property_name in properties_to_save[2]:
391400
if topomesh.has_wisp_property(property_name,2,is_computed=True):
392401
property_type = property_types[str(topomesh.wisp_property(property_name,2).values().dtype)]
@@ -447,6 +456,7 @@ def read_ply_property_topomesh(ply_filename, verbose = False):
447456
property_types['float32'] = 'float'
448457
property_types['list'] = 'list'
449458
property_types['tensor'] = 'tensor'
459+
property_types['string'] = 'str'
450460

451461
ply_file = open(ply_filename,'rU')
452462
ply_stream = enumerate(ply_file,1)
@@ -513,6 +523,9 @@ def read_ply_property_topomesh(ply_filename, verbose = False):
513523
elif property_types[prop_type] == 'int':
514524
line_props[prop] = int(re.split(' ',line)[prop_index])
515525
prop_index += 1
526+
elif property_types[prop_type] == 'str':
527+
line_props[prop] = str(re.split(' ',line)[prop_index])
528+
prop_index += 1
516529
elif property_types[prop_type] == 'list':
517530
list_length = int(re.split(' ',line)[prop_index])
518531
prop_index += 1

src/openalea/cellcomplex/property_topomesh/property_topomesh_optimization.py

Lines changed: 110 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -330,9 +330,7 @@ def property_topomesh_triangle_regularization_force(topomesh):
330330
#triangle_unitary_force = 0.02*area_unitary_force + 8.0*sinus_unitary_force
331331
# triangle_unitary_force = 0.02*area_unitary_force
332332

333-
triangle_force = np.transpose([nd.sum(triangle_unitary_force[:,0],triangle_vertices[:,0],index=list(topomesh.wisps(0))),
334-
nd.sum(triangle_unitary_force[:,1],triangle_vertices[:,0],index=list(topomesh.wisps(0))),
335-
nd.sum(triangle_unitary_force[:,2],triangle_vertices[:,0],index=list(topomesh.wisps(0)))])
333+
triangle_force = np.transpose([nd.sum(triangle_unitary_force[:,k],triangle_vertices[:,0],index=list(topomesh.wisps(0))) for k in xrange(3)])
336334

337335
return triangle_force
338336

@@ -962,13 +960,15 @@ def topomesh_remove_vertex(topomesh,pid,kept_fid=None,triangulate=True):
962960

963961

964962
def topomesh_collapse_edge(topomesh,eid,kept_pid=None,manifold=True):
963+
initial_topomesh = deepcopy(topomesh)
964+
965965
try:
966966
if manifold:
967967
assert len(list(topomesh.regions(1,eid))) == 2
968968

969969
pid_to_keep, pid_to_delete = topomesh.borders(1,eid)
970970

971-
print "--> Collapsing edge",eid," : ",pid_to_keep," ; ",pid_to_delete
971+
print "--> Trying to collapse edge",eid," : ",pid_to_keep," ; ",pid_to_delete
972972

973973
if kept_pid is not None and pid_to_keep != kept_pid:
974974
pid_to_delete, pid_to_keep = topomesh.borders(1,eid)
@@ -1000,8 +1000,8 @@ def topomesh_collapse_edge(topomesh,eid,kept_pid=None,manifold=True):
10001000
eid_to_keep = list(set(topomesh.borders(2,fid)).intersection(set(eids_to_keep)).difference({eid}))[0]
10011001
eid_to_delete = list(set(topomesh.borders(2,fid)).intersection(set(eids_to_delete)).difference({eid}))[0]
10021002

1003-
print " --> Kept eid : ",eid_to_keep,list(topomesh.regions(1,eid_to_keep))
1004-
print " --> Deleted eid : ",eid_to_delete,list(topomesh.regions(1,eid_to_delete))
1003+
print " --> Kept eid : ",eid_to_keep,list(topomesh.regions(1,eid_to_keep))
1004+
print " --> Deleted eid : ",eid_to_delete,list(topomesh.regions(1,eid_to_delete))
10051005

10061006
topomesh.unlink(2,fid,eid)
10071007
topomesh.unlink(2,fid,eid_to_keep)
@@ -1041,18 +1041,32 @@ def topomesh_collapse_edge(topomesh,eid,kept_pid=None,manifold=True):
10411041

10421042
topomesh.remove_wisp(1,eid)
10431043

1044-
print "<-- Collapsed edge",eid," : ",pid_to_keep
1044+
if np.max([topomesh.nb_regions(1,e) for e in topomesh.wisps(1)])>2:
1045+
print " --> Error while collapsing! Non-manifold edges :",np.array(list(topomesh.wisps(1)))[np.array([topomesh.nb_regions(1,e) for e in topomesh.wisps(1)])>2]
1046+
1047+
assert np.max([topomesh.nb_regions(1,e) for e in topomesh.wisps(1)])==2
1048+
1049+
print "<-- Collapsed edge",eid," : ",pid_to_keep," (",topomesh.nb_wisps(2)," Faces )"
1050+
#raw_input()
10451051

10461052
return True
10471053

10481054
# edge_vertices = np.sort(np.array([list(topomesh.borders(1,e)) for e in topomesh.wisps(1) if topomesh.nb_borders(1,e) == 2]))
10491055
# edge_vertex_id = edge_vertices[:,0]*10000 + edge_vertices[:,1]
10501056
# if edge_vertices.shape[0] != array_unique(edge_vertices).shape[0]:
1051-
# print eid," collapse error : (",pid_to_keep,pid_to_delete,")",np.array(list(topomesh.wisps(1)))[nd.sum(np.ones_like(edge_vertex_id),edge_vertex_id,index=edge_vertex_id)>1]
1057+
# print eid," collapse error : (",pid_to_keep,pid_to_delete,@")",np.array(list(topomesh.wisps(1)))[nd.sum(np.ones_like(edge_vertex_id),edge_vertex_id,index=edge_vertex_id)>1]
10521058
# raw_input()
10531059

10541060
except AssertionError:
1055-
print "Impossible to collapse edge : wrong configuration ( ",len(list(topomesh.regions(1,eid)))," regions)"
1061+
print "<-- Impossible to collapse edge : wrong configuration ( ",len(list(initial_topomesh.regions(1,eid)))," regions)"
1062+
assert np.max([initial_topomesh.nb_regions(1,e) for e in initial_topomesh.wisps(1)])==2
1063+
topomesh._borders = deepcopy(initial_topomesh._borders)
1064+
topomesh._regions = deepcopy(initial_topomesh._regions)
1065+
topomesh.update_wisp_property('barycenter',0,initial_topomesh.wisp_property('barycenter',0))
1066+
assert np.max([topomesh.nb_regions(1,e) for e in topomesh.wisps(1)])==2
1067+
1068+
print "<-- Failed to collapse edge",eid," : ",pid_to_keep," (",topomesh.nb_wisps(2)," Faces )"
1069+
# raw_input()
10561070
return False
10571071

10581072

@@ -1490,7 +1504,6 @@ def property_topomesh_edge_flip_optimization(topomesh,omega_energies=dict([('reg
14901504

14911505
if omega_energies.has_key('neighborhood'):
14921506

1493-
14941507
compute_topomesh_property(topomesh,'valence',0)
14951508

14961509
nested_mesh = kwargs.get("nested_mesh",False)
@@ -1570,23 +1583,104 @@ def property_topomesh_edge_split_optimization(topomesh, maximal_length=None, ite
15701583
return n_splits
15711584

15721585

1573-
def property_topomesh_isotropic_remeshing(initial_topomesh, maximal_length=None, iterations=1):
1586+
def property_topomesh_edge_collapse_optimization(topomesh, omega_energies=dict([('length',0.01),('error_quadrics',0.65)]), minimal_length=None, target_triangles=None, iterations=1):
1587+
1588+
compute_topomesh_property(topomesh,'vertices',1)
1589+
compute_topomesh_property(topomesh,'vertices',2)
1590+
compute_topomesh_property(topomesh,'length',1)
1591+
compute_topomesh_property(topomesh,'area',2)
1592+
1593+
if minimal_length is None:
1594+
target_length = np.percentile(topomesh.wisp_property('length',1).values(),70)
1595+
minimal_length = 3./4. * target_length
1596+
1597+
if target_triangles is None:
1598+
target_triangles = topomesh.nb_wisps(2)/4
1599+
1600+
if 'error_quadrics' in omega_energies.keys():
1601+
maximal_quadrics_error = np.power(minimal_length,2.)
1602+
1603+
compute_topomesh_property(topomesh,'triangles',0)
1604+
vertices_positions = topomesh.wisp_property('barycenter',0).values(topomesh.wisp_property('vertices',2).values())
1605+
normal_vectors = np.cross(vertices_positions[:,1]-vertices_positions[:,0],vertices_positions[:,2]-vertices_positions[:,0])
1606+
normal_norms = np.linalg.norm(normal_vectors,axis=1)
1607+
normal_vectors = normal_vectors/normal_norms[:,np.newaxis]
1608+
plane_d = -np.einsum('...ij,...ij->...i',normal_vectors,vertices_positions[:,0])
1609+
triangle_planes = np.concatenate([normal_vectors,plane_d[:,np.newaxis]],axis=1)
1610+
1611+
triangle_plane_quadrics = array_dict(np.einsum('...i,...j->...ij',triangle_planes,triangle_planes),list(topomesh.wisps(2)))
1612+
vertex_triangles = deepcopy(topomesh.wisp_property('triangles',0))
1613+
1614+
# vertex_quadrics = triangle_plane_quadrics.values([t[0]+1 for t in vertex_triangles])
1615+
# homogeneous_positions = np.concatenate([topomesh.wisp_property('barycenter',0).values(),np.ones((topomesh.nb_wisps(0),1))],axis=1)
1616+
1617+
for iterations in xrange(iterations):
1618+
compute_topomesh_property(topomesh,'vertices',1)
1619+
compute_topomesh_property(topomesh,'length',1)
1620+
1621+
edge_energy_variation = np.zeros_like(list(topomesh.wisps(1)),np.float)
1622+
1623+
if 'length' in omega_energies.keys():
1624+
edge_energy_variation += omega_energies['length']*(topomesh.wisp_property('length',1).values(list(topomesh.wisps(1))))
1625+
1626+
if 'error_quadrics' in omega_energies.keys():
1627+
1628+
edge_vertices = topomesh.wisp_property('vertices',1).values()
1629+
edge_middles = topomesh.wisp_property('barycenter',0).values(edge_vertices).mean(axis=1)
1630+
edge_middles_homogeneous = np.concatenate([edge_middles,np.ones((topomesh.nb_wisps(1),1))],axis=1)
1631+
1632+
edge_vertex_faces = np.array([np.concatenate(vertex_triangles.values(v)) for v in edge_vertices])
1633+
edge_vertex_face_quadrics = np.array([triangle_plane_quadrics.values(t) for t in edge_vertex_faces])
1634+
edge_vertex_face_middles = np.array([ [e for t in e_v_t] for e,e_v_t in zip(edge_middles_homogeneous,edge_vertex_faces)])
1635+
edge_quadrics_errors = np.array([np.abs(np.einsum('...ij,...ij->...i',m,np.einsum('...ij,...j->...i',q,m))).sum() for q,m in zip(edge_vertex_face_quadrics,edge_vertex_face_middles)])
1636+
edge_quadrics_errors = array_dict(edge_quadrics_errors,list(topomesh.wisps(1)))
1637+
1638+
edge_energy_variation += omega_energies['error_quadrics']*(edge_quadrics_errors.values(list(topomesh.wisps(1))))
1639+
1640+
sorted_energy_variation_edges = np.array(list(topomesh.wisps(1)))[np.argsort(edge_energy_variation)]
1641+
if 'error_quadrics' in omega_energies.keys():
1642+
sorted_energy_variation_edges = sorted_energy_variation_edges[edge_quadrics_errors.values(sorted_energy_variation_edges) < maximal_quadrics_error]
1643+
sorted_energy_variation_edges = sorted_energy_variation_edges[topomesh.wisp_property('length',1).values(sorted_energy_variation_edges) < minimal_length]
1644+
# sorted_quadrics_errors_edges = sorted_quadrics_errors_edges[np.sort(edge_quadrics_errors.values()) < np.percentile(edge_quadrics_errors.values(),5)]
1645+
1646+
modified_edges = set()
1647+
n_collapses = 0
1648+
for eid in sorted_energy_variation_edges:
1649+
if not eid in modified_edges and topomesh.nb_wisps(2)>target_triangles:
1650+
# print " <-- Collapsing edge ",eid," [",np.min(map(len,map(np.unique,[list(topomesh.borders(1,e)) for e in topomesh.wisps(1)]))),"]"
1651+
modified_edges = modified_edges.union(set(np.unique(list(topomesh.border_neighbors(1,eid))))).union({eid})
1652+
collapsed = topomesh_collapse_edge(topomesh,eid,manifold=False)
1653+
n_collapses += collapsed
1654+
# print " <-- Collapsed edge ",eid," [",np.min(map(len,map(np.unique,[list(topomesh.borders(1,e)) for e in topomesh.wisps(1)]))),"]"
1655+
print "--> Collapsed ",n_collapses," edges[",np.min(map(len,map(np.unique,[list(topomesh.borders(1,e)) for e in topomesh.wisps(1)]))),"]"
1656+
1657+
return n_collapses
1658+
1659+
1660+
def property_topomesh_isotropic_remeshing(initial_topomesh, maximal_length=None, minimal_length=None, collapse=False, iterations=1):
15741661

15751662
topomesh = deepcopy(initial_topomesh)
15761663

15771664
n_flips = topomesh.nb_wisps(1)
15781665
n_splits = topomesh.nb_wisps(1)
1666+
n_collapses = topomesh.nb_wisps(1)
15791667

1668+
compute_topomesh_property(topomesh,'length',1)
1669+
target_length = np.percentile(topomesh.wisp_property('length',1).values(),80)
15801670
if maximal_length is None:
1581-
compute_topomesh_property(topomesh,'length',1)
1582-
target_length = np.percentile(topomesh.wisp_property('length',1).values(),50)
15831671
maximal_length = 4./3. * target_length
1672+
if minimal_length is None:
1673+
minimal_length = 3./4. * target_length
15841674

15851675
iteration = 0
1586-
while (n_flips+n_splits > topomesh.nb_wisps(1)/100.) and (iteration<iterations):
1676+
while (n_flips+n_splits+n_collapses > topomesh.nb_wisps(1)/100.) and (iteration<iterations):
1677+
if collapse:
1678+
n_collapses = property_topomesh_edge_collapse_optimization(topomesh, minimal_length=minimal_length, iterations=1)
1679+
else:
1680+
n_collapses = 0
15871681
n_splits = property_topomesh_edge_split_optimization(topomesh, maximal_length=maximal_length, iterations=1)
1588-
n_flips = property_topomesh_edge_flip_optimization(topomesh,omega_energies=dict([('neighborhood',0.65)]),simulated_annealing=False,iterations=3)
1589-
property_topomesh_vertices_deformation(topomesh,omega_forces=dict([('taubin_smoothing',0.33)]))
1682+
n_flips = property_topomesh_edge_flip_optimization(topomesh,omega_energies=dict([('neighborhood',0.65)]),simulated_annealing=False,iterations=5)
1683+
property_topomesh_vertices_deformation(topomesh,omega_forces=dict([('taubin_smoothing',0.33)]),iterations=5)
15901684
iteration += 1
15911685

15921686
return topomesh

src/openalea/cellcomplex/property_topomesh/triangular_mesh.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,18 @@
2020
import numpy as np
2121
from openalea.container import array_dict
2222

23-
from openalea.cellcomplex.property_topomesh.property_topomesh_analysis import compute_topomesh_property
23+
from openalea.cellcomplex.property_topomesh.property_topomesh_analysis import compute_topomesh_property, is_triangular
24+
from openalea.cellcomplex.property_topomesh.property_topomesh_extraction import star_interface_topomesh
2425
from openalea.cellcomplex.triangular_mesh import TriangularMesh
2526

2627
from time import time
28+
from copy import deepcopy
2729

28-
def topomesh_to_triangular_mesh(topomesh, degree=3, coef=1.0, mesh_center=None, epidermis=False, cell_edges=False, property_name=None, property_degree=None):
30+
def topomesh_to_triangular_mesh(input_topomesh, degree=3, coef=1.0, mesh_center=None, epidermis=False, cell_edges=False, property_name=None, property_degree=None):
2931

32+
topomesh = deepcopy(input_topomesh)
33+
if not is_triangular(topomesh):
34+
topomesh = star_interface_topomesh(topomesh)
3035

3136
start_time = time()
3237
print "--> Creating triangular mesh"
@@ -80,6 +85,7 @@ def topomesh_to_triangular_mesh(topomesh, degree=3, coef=1.0, mesh_center=None,
8085
triangle_vertices += list(cell_vertices_index.values(topomesh.wisp_property('vertices',2).values(topomesh.wisp_property('triangles',3)[c])))
8186
triangle_topomesh_cells += list(c*np.ones_like(topomesh.wisp_property('triangles',3)[c]))
8287
# triangle_topomesh_triangles += topomesh.wisp_property('triangles',3)[c]
88+
print vertices_positions
8389
vertices_positions = array_dict(vertices_positions,np.arange(len(vertices_positions)))
8490
vertices_topomesh_vertices = array_dict(vertices_topomesh_vertices,np.arange(len(vertices_positions)))
8591
if epidermis:

0 commit comments

Comments
 (0)