wolfhece 2.1.20__py3-none-any.whl → 2.1.22__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,8 @@ from wx.dataview import *
6
6
  from wx.core import BoxSizer, FlexGridSizer, TreeItemId
7
7
  from OpenGL.GL import *
8
8
  from shapely.geometry import LineString, MultiLineString,Point,MultiPoint,Polygon,JOIN_STYLE, MultiPolygon
9
- from shapely.ops import nearest_points,substring, split
9
+ from shapely.ops import nearest_points,substring, split, polygonize
10
+ from shapely import delaunay_triangles
10
11
  import pygltflib
11
12
  from scipy.interpolate import interp1d
12
13
  import matplotlib.pyplot as plt
@@ -1171,6 +1172,22 @@ class vector:
1171
1172
 
1172
1173
  coords=self.asnparray()
1173
1174
  return Polygon(coords)
1175
+
1176
+ def asshapely_pol3D(self) -> Polygon:
1177
+ """
1178
+ Conversion des coordonnées en Polygon Shapely
1179
+ """
1180
+
1181
+ coords=self.asnparray3d()
1182
+ return Polygon(coords)
1183
+
1184
+ def asshapely_ls3d(self) -> LineString:
1185
+ """
1186
+ Conversion des coordonnées en Linestring Shapely
1187
+ """
1188
+
1189
+ coords=self.asnparray3d()
1190
+ return LineString(coords)
1174
1191
 
1175
1192
  def asshapely_ls(self) -> LineString:
1176
1193
  """
@@ -1508,25 +1525,32 @@ class vector:
1508
1525
  If the vector has no interior, the list contains the whole vector as a polygon
1509
1526
  """
1510
1527
 
1511
- if self.has_interior:
1512
- not_in_use = [curvert for curvert in self.myvertices if not curvert.in_use]
1528
+ if self.myprop.filled:
1529
+ return [self.myvertices]
1513
1530
 
1514
- alls = []
1515
- new_poly = []
1516
- for curvert in self.myvertices:
1517
- if curvert in not_in_use:
1518
- alls.append(new_poly)
1519
- new_poly = []
1520
- new_poly.append(curvert)
1521
- else:
1522
- new_poly.append(curvert)
1531
+ else:
1532
+ if self.has_interior:
1533
+ # not_in_use = [curvert for curvert in self.myvertices if not curvert.in_use]
1523
1534
 
1524
- if self.myprop.closed and (self.myvertices[0].x != self.myvertices[-1].x or self.myvertices[0].y != self.myvertices[-1].y):
1525
- alls[0].append(self.myvertices[0])
1535
+ alls = []
1526
1536
 
1527
- return alls
1528
- else:
1529
- return [self.myvertices]
1537
+ new_poly = []
1538
+ alls.append(new_poly)
1539
+
1540
+ for curvert in self.myvertices:
1541
+ if curvert.in_use:
1542
+ new_poly.append(curvert)
1543
+ else:
1544
+ new_poly = []
1545
+ alls.append(new_poly)
1546
+ new_poly.append(curvert)
1547
+
1548
+ if self.myprop.closed and (self.myvertices[0].x != self.myvertices[-1].x or self.myvertices[0].y != self.myvertices[-1].y):
1549
+ alls[0].append(self.myvertices[0])
1550
+
1551
+ return alls
1552
+ else:
1553
+ return [self.myvertices]
1530
1554
 
1531
1555
  def plot(self, sx=None, sy=None, xmin=None, ymin=None, xmax=None, ymax=None, size=None):
1532
1556
  """
@@ -1556,26 +1580,54 @@ class vector:
1556
1580
  else:
1557
1581
  glColor3ub(int(rgb[0]),int(rgb[1]),int(rgb[2]))
1558
1582
 
1559
- all_polys = self.get_subpolygons()
1583
+ if self.myprop.filled:
1560
1584
 
1561
- for curpoly in all_polys:
1585
+ import triangle
1586
+
1587
+ ls = self.asshapely_pol()
1588
+
1589
+ if False:
1590
+
1591
+ #FIXME : Shapely have not constrained Delaunay triangulation -- using Delaunay from Wolf Fortran instead
1592
+ ls = ls.segmentize(.1)
1593
+ delaunay = delaunay_triangles(ls)
1594
+
1595
+ for curpol in delaunay.geoms:
1596
+ if ls.contains(curpol.centroid):
1597
+ glBegin(GL_POLYGON)
1598
+ for curvert in curpol.exterior.coords:
1599
+ glVertex2d(curvert[0],curvert[1])
1600
+ glEnd()
1601
+ else:
1602
+ logging.debug(_('Polygon not in Polygon'))
1562
1603
 
1563
- if self.myprop.filled:
1564
- glBegin(GL_POLYGON)
1565
1604
  else:
1605
+ #En attendant de lier WOLF-Fortran, on utilise la triangulation contrainte de la librairie Triangle -- https://rufat.be/triangle/
1606
+ xx, yy = ls.exterior.xy
1607
+ geom = {'vertices' : np.array([xx,yy]).T, 'segments' : np.array([[i,i+1] for i in range(len(xx)-1)]+[[len(xx)-1,0]])}
1608
+ delaunay = triangle.triangulate(geom,'p')
1609
+
1610
+ for curtri in delaunay['triangles']:
1611
+ glBegin(GL_POLYGON)
1612
+ for i in range(3):
1613
+ glVertex2d(delaunay['vertices'][curtri[i]][0],delaunay['vertices'][curtri[i]][1])
1614
+ glEnd()
1615
+
1616
+ else:
1617
+ all_polys = self.get_subpolygons()
1618
+
1619
+ for curpoly in all_polys:
1620
+
1566
1621
  glBegin(GL_LINE_STRIP)
1567
1622
 
1568
- for curvertex in curpoly:
1569
- glVertex2d(curvertex.x, curvertex.y)
1623
+ for curvertex in curpoly:
1624
+ glVertex2d(curvertex.x, curvertex.y)
1570
1625
 
1571
- glEnd()
1626
+ glEnd()
1572
1627
 
1573
1628
  glPolygonMode(GL_FRONT_AND_BACK,GL_LINE)
1574
1629
  glDisable(GL_BLEND)
1575
1630
 
1576
- # if self.myprop.legendvisible:
1577
- # self.textimage.paint()
1578
-
1579
1631
  def plot_legend(self, sx=None, sy=None, xmin=None, ymin=None, xmax=None, ymax=None, size=None):
1580
1632
  """
1581
1633
  Plot OpenGL
@@ -1661,7 +1713,7 @@ class vector:
1661
1713
 
1662
1714
  self.parentzone.reset_listogl()
1663
1715
 
1664
- def fillgrid(self,gridto:CpGrid):
1716
+ def fillgrid(self, gridto:CpGrid):
1665
1717
  """
1666
1718
  Remplissage d'un CpGrid
1667
1719
  """
@@ -1672,6 +1724,7 @@ class vector:
1672
1724
  gridto.SetColLabelValue(2,'Z')
1673
1725
  gridto.SetColLabelValue(3,'value')
1674
1726
  gridto.SetColLabelValue(4,'s curvi')
1727
+ gridto.SetColLabelValue(5,'in use')
1675
1728
 
1676
1729
  nb=gridto.GetNumberRows()
1677
1730
  if len(self.myvertices)-nb>0:
@@ -1681,6 +1734,7 @@ class vector:
1681
1734
  gridto.SetCellValue(k,0,str(curv.x))
1682
1735
  gridto.SetCellValue(k,1,str(curv.y))
1683
1736
  gridto.SetCellValue(k,2,str(curv.z))
1737
+ gridto.SetCellValue(k,5,'1' if curv.in_use else '0')
1684
1738
  k+=1
1685
1739
 
1686
1740
  def updatefromgrid(self,gridfrom:CpGrid):
@@ -1695,6 +1749,7 @@ class vector:
1695
1749
  x=gridfrom.GetCellValue(k,0)
1696
1750
  y=gridfrom.GetCellValue(k,1)
1697
1751
  z=gridfrom.GetCellValue(k,2)
1752
+ inuse = gridfrom.GetCellValue(k,5)
1698
1753
  if z=='':
1699
1754
  z=0.
1700
1755
  if x!='':
@@ -1702,6 +1757,7 @@ class vector:
1702
1757
  self.myvertices[k].x=float(x)
1703
1758
  self.myvertices[k].y=float(y)
1704
1759
  self.myvertices[k].z=float(z)
1760
+ self.myvertices[k].in_use = inuse=='1'
1705
1761
  else:
1706
1762
  newvert=wolfvertex(float(x),float(y),float(z))
1707
1763
  self.add_vertex(newvert)
@@ -1715,6 +1771,8 @@ class vector:
1715
1771
  if self.linestring is not None:
1716
1772
  self.prepare_shapely()
1717
1773
 
1774
+ self.parentzone.reset_listogl()
1775
+
1718
1776
  def get_s2d(self):
1719
1777
  """
1720
1778
  calcul et retour des positions curvilignes 2D
@@ -3842,7 +3900,7 @@ class Zones(wx.Frame, Element_To_Draw):
3842
3900
  self.set_mapviewer()
3843
3901
 
3844
3902
  try:
3845
- super(Zones, self).__init__(None, size=(300, 400))
3903
+ super(Zones, self).__init__(None, size=(400, 400))
3846
3904
  self.Bind(wx.EVT_CLOSE,self.OnClose) # on lie la procédure de fermeture de façon à juste masquer le Frame et non le détruire
3847
3905
  except:
3848
3906
  raise Warning(_('Bad wx context -- see Zones.__init__'))
@@ -3925,7 +3983,12 @@ class Zones(wx.Frame, Element_To_Draw):
3925
3983
  return len(self.myzones)
3926
3984
 
3927
3985
  def import_shapefile(self, fn:str, bbox:Polygon = None):
3928
- """ Import shapefile by using geopandas """
3986
+ """
3987
+ Import shapefile by using geopandas
3988
+
3989
+ Shapefile == 1 zone
3990
+
3991
+ """
3929
3992
 
3930
3993
  content = gpd.read_file(fn, bbox=bbox)
3931
3994
 
@@ -3945,6 +4008,60 @@ class Zones(wx.Frame, Element_To_Draw):
3945
4008
  newzone = zone(name=name, parent = self, fromshapely = poly)
3946
4009
  self.add_zone(newzone)
3947
4010
 
4011
+ def export_to_shapefile(self, filename:str):
4012
+ """
4013
+ Export to shapefile.
4014
+
4015
+ The first vector of each zone will be exported.
4016
+
4017
+ If you want to export all vectors, you have to use "export_shape" of the zone object.
4018
+
4019
+ FIXME: Add support of data fields
4020
+ """
4021
+
4022
+ import geopandas as gpd
4023
+
4024
+ names=[]
4025
+ geoms=[]
4026
+
4027
+ # One zone is a polygon
4028
+ for curzone in self.myzones:
4029
+ if curzone.nbvectors == 0:
4030
+ logging.warning(_('Zone {} contains no vector'.format(curzone.myname)))
4031
+ continue
4032
+
4033
+ elif curzone.nbvectors>1:
4034
+ logging.warning(_('Zone {} contains more than one vector -- only the first one will be exported'.format(curzone.myname)))
4035
+
4036
+ names.append(curzone.myname)
4037
+ for curvect in curzone.myvectors[:1]:
4038
+ if curvect.is2D:
4039
+ if curvect.closed:
4040
+ geoms.append(curvect.asshapely_pol())
4041
+ else:
4042
+ geoms.append(curvect.asshapely_ls())
4043
+ else:
4044
+ if curvect.closed:
4045
+ geoms.append(curvect.asshapely_pol3D())
4046
+ else:
4047
+ geoms.append(curvect.asshapely_ls3d())
4048
+
4049
+ gdf = gpd.GeoDataFrame({'id':names,'geometry':geoms})
4050
+ gdf.crs = 'EPSG:31370'
4051
+
4052
+ gdf.to_file(filename)
4053
+
4054
+ def export_active_zone_to_shapefile(self, filename:str):
4055
+ """
4056
+ Export the active_zone to shapefile.
4057
+ """
4058
+
4059
+ if self.active_zone is None:
4060
+ logging.warning(_('No active zone'))
4061
+ return
4062
+
4063
+ self.active_zone.export_shape(filename)
4064
+
3948
4065
  def import_gdb(self, fn:str, bbox:Polygon = None):
3949
4066
  """ Import gdb by using geopandas and Fiona"""
3950
4067
 
@@ -4260,7 +4377,7 @@ class Zones(wx.Frame, Element_To_Draw):
4260
4377
  """
4261
4378
  self.plotted = False
4262
4379
 
4263
- def saveas(self, filename=''):
4380
+ def saveas(self, filename:str=''):
4264
4381
  """
4265
4382
  Sauvegarde sur disque
4266
4383
 
@@ -4271,18 +4388,22 @@ class Zones(wx.Frame, Element_To_Draw):
4271
4388
  if filename!='':
4272
4389
  self.filename=filename
4273
4390
 
4274
- if self.filename.endswith('.vecz'):
4275
- self.force3D=True #on veut un fichier 3D --> forcage du paramètre
4391
+ if self.filename.endswith('.shp'):
4392
+ self.export_to_shapefile(self.filename)
4276
4393
 
4277
- with open(self.filename, 'w') as f:
4278
- f.write(f'{self.tx} {self.ty}'+'\n')
4279
- f.write(str(self.nbzones)+'\n')
4280
- for curzone in self.myzones:
4281
- curzone.save(f)
4394
+ else:
4395
+ if self.filename.endswith('.vecz'):
4396
+ self.force3D=True #on veut un fichier 3D --> forcage du paramètre
4282
4397
 
4283
- with open(self.filename + '.extra', 'w') as f:
4284
- for curzone in self.myzones:
4285
- curzone.save_extra(f)
4398
+ with open(self.filename, 'w') as f:
4399
+ f.write(f'{self.tx} {self.ty}'+'\n')
4400
+ f.write(str(self.nbzones)+'\n')
4401
+ for curzone in self.myzones:
4402
+ curzone.save(f)
4403
+
4404
+ with open(self.filename + '.extra', 'w') as f:
4405
+ for curzone in self.myzones:
4406
+ curzone.save_extra(f)
4286
4407
 
4287
4408
  def OnClose(self, e):
4288
4409
  """
@@ -4405,7 +4526,7 @@ class Zones(wx.Frame, Element_To_Draw):
4405
4526
  boxupdownz = BoxSizer(orient=wx.VERTICAL)
4406
4527
 
4407
4528
  self.xls=CpGrid(self,-1,wx.WANTS_CHARS)
4408
- self.xls.CreateGrid(10,5)
4529
+ self.xls.CreateGrid(10,6)
4409
4530
 
4410
4531
  self.addrows = wx.Button(self,label=_('Add rows'))
4411
4532
  self.addrows.SetToolTip(_("Add rows to the grid --> Useful for manually adding some points to a vector"))
wolfhece/apps/version.py CHANGED
@@ -5,7 +5,7 @@ class WolfVersion():
5
5
 
6
6
  self.major = 2
7
7
  self.minor = 1
8
- self.patch = 20
8
+ self.patch = 22
9
9
 
10
10
  def __str__(self):
11
11
 
File without changes