wolfhece 2.1.128__py3-none-any.whl → 2.2.1__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.
- wolfhece/PyDraw.py +109 -46
- wolfhece/PyGui.py +3 -0
- wolfhece/PyGuiHydrology.py +24 -24
- wolfhece/PyPalette.py +27 -11
- wolfhece/PyParams.py +5 -1
- wolfhece/PyVertexvectors.py +52 -7
- wolfhece/Results2DGPU.py +17 -0
- wolfhece/acceptability/acceptability_gui.py +29 -18
- wolfhece/acceptability/func.py +23 -21
- wolfhece/apps/version.py +2 -2
- wolfhece/eikonal.py +1 -1
- wolfhece/hydrology/Catchment.py +113 -12
- wolfhece/hydrology/Comparison.py +54 -52
- wolfhece/hydrology/Optimisation.py +309 -178
- wolfhece/hydrology/PostProcessHydrology.py +6 -3
- wolfhece/hydrology/RetentionBasin.py +21 -14
- wolfhece/hydrology/SubBasin.py +128 -12
- wolfhece/hydrology/constant.py +3 -0
- wolfhece/hydrology/cst_exchanges.py +364 -38
- wolfhece/hydrology/plot_hydrology.py +34 -18
- wolfhece/hydrology/read.py +16 -6
- wolfhece/lagrangian/particle_system_ui.py +1 -1
- wolfhece/lagrangian/particles.py +1 -1
- wolfhece/lazviewer/processing/estimate_normals/estimate_normals.cp310-win_amd64.pyd +0 -0
- wolfhece/lazviewer/vfuncsdir/vfuncs.cp310-win_amd64.pyd +0 -0
- wolfhece/lazviewer/viewer/viewer.exe +0 -0
- wolfhece/lazviewer/viewer/viewer_np1_23_5.exe +0 -0
- wolfhece/libs/WolfDll.dll +0 -0
- wolfhece/libs/Wolf_tools.dll +0 -0
- wolfhece/libs/get_infos.cp310-win_amd64.pyd +0 -0
- wolfhece/libs/verify_wolf.cp310-win_amd64.pyd +0 -0
- wolfhece/libs/wolfogl.cp310-win_amd64.pyd +0 -0
- wolfhece/radar/wolfradar.py +75 -22
- wolfhece/shapes/__init__.py +0 -0
- wolfhece/shapes/circle.py +335 -0
- wolfhece/tools2d_dll.py +359 -0
- wolfhece/wolf_array.py +3 -2
- wolfhece/wolfresults_2D.py +162 -33
- {wolfhece-2.1.128.dist-info → wolfhece-2.2.1.dist-info}/METADATA +15 -9
- {wolfhece-2.1.128.dist-info → wolfhece-2.2.1.dist-info}/RECORD +43 -39
- wolfhece/libs/wolfpy.cp310-win_amd64.pyd +0 -0
- {wolfhece-2.1.128.dist-info → wolfhece-2.2.1.dist-info}/WHEEL +0 -0
- {wolfhece-2.1.128.dist-info → wolfhece-2.2.1.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.1.128.dist-info → wolfhece-2.2.1.dist-info}/top_level.txt +0 -0
wolfhece/hydrology/read.py
CHANGED
@@ -14,6 +14,7 @@ import logging
|
|
14
14
|
from datetime import datetime as date
|
15
15
|
from datetime import timezone
|
16
16
|
from struct import unpack, calcsize, unpack_from
|
17
|
+
from pathlib import Path
|
17
18
|
|
18
19
|
|
19
20
|
# Constants
|
@@ -102,8 +103,8 @@ def read_bin_old(path, fileName, nbBytes=[], uniform_format=-1, hydro=False) ->
|
|
102
103
|
nbL = int.from_bytes(num, byteorder='little', signed=True)
|
103
104
|
num = f.read(4)
|
104
105
|
nbC = int.from_bytes(num, byteorder='little', signed=True)
|
105
|
-
print("nb lines = ", nbL)
|
106
|
-
print("nb col = ", nbC)
|
106
|
+
# print("nb lines = ", nbL)
|
107
|
+
# print("nb col = ", nbC)
|
107
108
|
|
108
109
|
if nbBytes==[]:
|
109
110
|
if uniform_format == -1:
|
@@ -201,6 +202,10 @@ def read_binary_file(path, fileName, format="", buffer_size=-1, init_offset=8):
|
|
201
202
|
|
202
203
|
def is_relative_path(path:str):
|
203
204
|
|
205
|
+
if path is None:
|
206
|
+
logging.error("The path is None")
|
207
|
+
return False
|
208
|
+
|
204
209
|
isRelativePath = False
|
205
210
|
|
206
211
|
if len(path)>0:
|
@@ -240,7 +245,7 @@ def relative_2_absolute(fileName:str, prefix:str="", applyCWD:bool=True)-> tuple
|
|
240
245
|
def read_hydro_file(path:str, fileName:str, nbCol:int=6, nbCol_data:int=1) -> tuple[np.array, np.array]:
|
241
246
|
format_bin = "<bbhbbbd"
|
242
247
|
header_offset = 8
|
243
|
-
|
248
|
+
|
244
249
|
data = read_binary_file(path, fileName, format=format_bin, init_offset=header_offset)
|
245
250
|
data = np.array(data).astype("double")
|
246
251
|
time, value = parse_hydro_data(data)
|
@@ -272,7 +277,7 @@ def write_excel_from_dict(data:dict[str:dict[str:np.array]], path:str, fileName:
|
|
272
277
|
# if the dictionary is empty, skip the station -> no creation of the sheet
|
273
278
|
if values == {}:
|
274
279
|
continue
|
275
|
-
|
280
|
+
|
276
281
|
excl_dict = {}
|
277
282
|
if time is not None:
|
278
283
|
excl_dict["Time [s]"] = time
|
@@ -283,7 +288,7 @@ def write_excel_from_dict(data:dict[str:dict[str:np.array]], path:str, fileName:
|
|
283
288
|
curSheet.to_excel(writer, sheet_name=station, index=False)
|
284
289
|
curSheet = writer.sheets[station]
|
285
290
|
curSheet.autofit()
|
286
|
-
|
291
|
+
|
287
292
|
# if the summary is empty, skip the summary -> no creation of the sheet
|
288
293
|
if summary != {}:
|
289
294
|
curSheet = pd.DataFrame(summary)
|
@@ -292,7 +297,7 @@ def write_excel_from_dict(data:dict[str:dict[str:np.array]], path:str, fileName:
|
|
292
297
|
curSheet.autofit()
|
293
298
|
|
294
299
|
writer.close()
|
295
|
-
|
300
|
+
|
296
301
|
return
|
297
302
|
|
298
303
|
def check_path(fileName:str, prefix:str="", applyCWD:bool=True) -> tuple[bool, str] :
|
@@ -302,6 +307,11 @@ def check_path(fileName:str, prefix:str="", applyCWD:bool=True) -> tuple[bool, s
|
|
302
307
|
info = -2
|
303
308
|
return info
|
304
309
|
|
310
|
+
if fileName is None:
|
311
|
+
logging.error("The file name is None")
|
312
|
+
info = -3
|
313
|
+
return info, fileName
|
314
|
+
|
305
315
|
isPresent = os.path.exists(finalName)
|
306
316
|
|
307
317
|
if(not(isPresent)):
|
@@ -397,7 +397,7 @@ class Particle_system_to_draw(Element_To_Draw):
|
|
397
397
|
self._ps.nbx, self._ps.nby = value.array.shape
|
398
398
|
self._ps.dx, self._ps.dy = value.dx, value.dy
|
399
399
|
else:
|
400
|
-
assert value.dtype == np.
|
400
|
+
assert value.dtype == np.bool, 'Domain must be boolean'
|
401
401
|
self._ps.domain = value
|
402
402
|
self._ps.nbx, self._ps.nby = value.shape
|
403
403
|
|
wolfhece/lagrangian/particles.py
CHANGED
@@ -38,7 +38,7 @@ class Particles():
|
|
38
38
|
|
39
39
|
self.start_position = [x0, y0]
|
40
40
|
self.end_position = [x0.copy(), y0.copy()] # copy to define new memory storage
|
41
|
-
self._is_alive = np.ones_like(x0, dtype=np.
|
41
|
+
self._is_alive = np.ones_like(x0, dtype=np.bool)
|
42
42
|
|
43
43
|
def copy_prop_from(self, other:'Particles') -> None:
|
44
44
|
"""
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
wolfhece/libs/WolfDll.dll
CHANGED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
wolfhece/radar/wolfradar.py
CHANGED
@@ -19,7 +19,16 @@ from datetime import timezone
|
|
19
19
|
from os import path
|
20
20
|
from osgeo import gdal, osr
|
21
21
|
from ..drawing_obj import Element_To_Draw
|
22
|
+
from tqdm import tqdm
|
22
23
|
|
24
|
+
RADQPE = 1
|
25
|
+
RADCLIM = 2
|
26
|
+
RADFLOOD = 3
|
27
|
+
|
28
|
+
FILL_NONE = 0
|
29
|
+
FILL_ZERO = 1
|
30
|
+
FILL_NAN = 2
|
31
|
+
FILL_INTERP = 3
|
23
32
|
|
24
33
|
class L08L72:
|
25
34
|
epsgL08:osr.SpatialReference
|
@@ -51,12 +60,13 @@ class RadarIRM(Element_To_Draw):
|
|
51
60
|
|
52
61
|
|
53
62
|
def convert2rain(self, coordMin:tuple, coordMax:tuple, dateBegin:date, dateEnd:date, deltaT:tdelta,
|
54
|
-
dirIn:str="", dirOut:str="",
|
55
|
-
check_all_polygons:bool=False):
|
63
|
+
dirIn:str="", dirOut:str="", file_name_conv:str=".radclim.accum", type_rain:int=RADCLIM, recursive_dir="",
|
64
|
+
check_all_polygons:bool=False, fill_data:int=FILL_NONE):
|
56
65
|
|
57
|
-
from datetime import datetime as date
|
58
66
|
# =================
|
59
67
|
# ALL VERIFICATIONS :
|
68
|
+
logging.info("Starting the conversion of IRM data to rain data ...")
|
69
|
+
logging.info("Verification ongoing ...")
|
60
70
|
|
61
71
|
# Checking the validity of the repository to read and write :
|
62
72
|
isOk, dirIn = check_path(dirIn, applyCWD=True)
|
@@ -74,12 +84,21 @@ class RadarIRM(Element_To_Draw):
|
|
74
84
|
dt = deltaT.total_seconds()
|
75
85
|
nb_intervals = floor((dateEnd - dateBegin).total_seconds() / dt)
|
76
86
|
time = [dateBegin + tdelta(seconds=dt*i) for i in range(nb_intervals + 1)]
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
87
|
+
if recursive_dir == "":
|
88
|
+
# Prefix for dates -> only if it's not a recursive directory
|
89
|
+
dt_str = "{:.0f}d".format(deltaT.days)*(deltaT.days>0) \
|
90
|
+
+ "{:.0f}h".format(floor(deltaT.seconds)/3600)*(floor(deltaT.seconds/3600)>0) \
|
91
|
+
+ "{:.0f}m".format(floor(deltaT.seconds%3600)/60)*(floor(deltaT.seconds%3600)/60>0)
|
92
|
+
suffix = "".join([file_name_conv, dt_str, ".hdf"])
|
93
|
+
all_files = [os.path.join(dirIn,"".join([t.strftime("%Y%m%d%H%M%S"),suffix])) for t in time]
|
94
|
+
else:
|
95
|
+
suffix = "".join([file_name_conv, ".hdf"])
|
96
|
+
all_files = [os.path.join(dirIn,
|
97
|
+
t.strftime("%Y"),
|
98
|
+
t.strftime("%m"),
|
99
|
+
t.strftime("%d"),
|
100
|
+
recursive_dir,
|
101
|
+
"".join([t.strftime("%Y%m%d%H%M%S"),suffix])) for t in time]
|
83
102
|
# are_present = np.all(np.array( \
|
84
103
|
# [os.path.exists(os.path.join(dirIn,"".join([t.strftime("%Y%m%d%H%M%S"),suffix]))) for t in time] \
|
85
104
|
# ))
|
@@ -90,7 +109,14 @@ class RadarIRM(Element_To_Draw):
|
|
90
109
|
|
91
110
|
if not are_present:
|
92
111
|
logging.error("Rain files present in the selected directory are does not contain all the information between the desired interval.")
|
93
|
-
|
112
|
+
i_problem = np.where(np.array([os.path.exists(el) for el in all_files]) == False)[0]
|
113
|
+
logging.error("The following files are missing :")
|
114
|
+
for i in i_problem:
|
115
|
+
logging.error(all_files[i])
|
116
|
+
if fill_data == FILL_NONE:
|
117
|
+
logging.error("The process stops because there are missing files!")
|
118
|
+
logging.error("To make an linear interpolation set to False 'no_missing_files' argument.")
|
119
|
+
return
|
94
120
|
|
95
121
|
# Creating the direcory results
|
96
122
|
# Directory of the shapefile
|
@@ -118,12 +144,15 @@ class RadarIRM(Element_To_Draw):
|
|
118
144
|
else:
|
119
145
|
print ("Successfully created the directory %s" % timeSeriesDir)
|
120
146
|
|
147
|
+
logging.info("Verification validated!")
|
121
148
|
|
122
149
|
# =================
|
123
150
|
# CORE PROCEDURE
|
124
151
|
# After all verifications, the core procedure can now start :
|
125
152
|
# extract all the points in all the .hdf files and their values -> check whether to crop during this process of after
|
126
153
|
|
154
|
+
logging.info("Creation of the shapefile ongoing ...")
|
155
|
+
|
127
156
|
# Definition of the domaine zone
|
128
157
|
limits = vector()
|
129
158
|
limits.add_vertex(wolfvertex(coordMin[0],coordMin[1]))
|
@@ -173,27 +202,52 @@ class RadarIRM(Element_To_Draw):
|
|
173
202
|
|
174
203
|
# save the polygons in .shp shapefile
|
175
204
|
polygons.export_shape(fileOut)
|
205
|
+
logging.info("Creation of the shapefile finished !")
|
176
206
|
|
177
|
-
|
207
|
+
logging.info("Creation of polygon time series ongoing ...")
|
178
208
|
# Create a folder with the time serie for each polygone
|
179
209
|
timeStps = [[str(t.day), str(t.month), str(t.year), str(t.hour), str(t.minute), str(t.second)] for t in time]
|
180
210
|
|
181
211
|
all_values = np.zeros((len(all_files), polygons.nbvectors))
|
182
|
-
for i in range(len(all_files)):
|
212
|
+
for i in tqdm(range(len(all_files))):
|
183
213
|
cur_file = all_files[i]
|
214
|
+
exists = os.path.exists(cur_file)
|
184
215
|
try:
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
216
|
+
if exists:
|
217
|
+
hdf_ds = gdal.Open(cur_file, gdal.GA_ReadOnly)
|
218
|
+
values, coord, proj = wrl.georef.raster.extract_raster_dataset(hdf_ds, mode="edge", nodata=0.0)
|
219
|
+
vec_values = values.reshape(-1)
|
220
|
+
all_values[i,:] = np.nan_to_num([vec_values[i] for i in zones_indices], copy=False, nan=0.0)
|
221
|
+
# FIXME this following line -> to check !!!! -> Convert [mm/h] to accumulated rain [mm] at each time step
|
222
|
+
# radflood
|
223
|
+
if type_rain == RADFLOOD or type_rain == RADCLIM:
|
224
|
+
all_values[i,:] = all_values[i,:]
|
225
|
+
elif type_rain == RADQPE:
|
226
|
+
# radqpe
|
227
|
+
# TODO : check the conversion for radclim
|
228
|
+
all_values[i,:] = all_values[i,:]*(dt/3600.0)
|
229
|
+
# all_values[i,:] = all_values[i,:]*(dt/3600.0)
|
230
|
+
else:
|
231
|
+
if fill_data == FILL_ZERO:
|
232
|
+
all_values[i,:] = 0.0
|
233
|
+
else:
|
234
|
+
all_values[i,:] = np.nan
|
191
235
|
except:
|
192
236
|
logging.error("".join(["Something bad happened while reading hdf file :", cur_file]))
|
193
237
|
all_values[i,:] = 0.0
|
194
|
-
|
238
|
+
logging.info("Creation of polygon time series finished !")
|
239
|
+
|
240
|
+
logging.info("Writing polygon time series ongoing ...")
|
195
241
|
# Writing the file
|
196
|
-
for iVec in range(polygons.nbvectors):
|
242
|
+
for iVec in tqdm(range(polygons.nbvectors)):
|
243
|
+
# Clean the nan value with linear interpolation
|
244
|
+
# FIXME : to check the interpolation
|
245
|
+
if(fill_data == FILL_INTERP):
|
246
|
+
logging.warning('Interpolating missing values in the time series -> Still to test!')
|
247
|
+
valid = ~np.isnan(all_values[:,iVec])
|
248
|
+
invalid = np.isnan(all_values[:,iVec])
|
249
|
+
all_values[invalid,iVec] = np.interp(np.flatnonzero(invalid), np.flatnonzero(valid), all_values[valid,iVec])
|
250
|
+
# write in the file
|
197
251
|
with open(os.path.join(timeSeriesDir,"".join([str(iVec+1),".rain"])), 'w') as f:
|
198
252
|
f.write("".join([str(iVec+1),"\n"]))
|
199
253
|
f.write("".join([str(1),"\n"]))
|
@@ -201,11 +255,10 @@ class RadarIRM(Element_To_Draw):
|
|
201
255
|
f.write("".join([str(len(all_files)),"\n"]))
|
202
256
|
for cur_t in range(len(timeStps)):
|
203
257
|
f.write("\t".join(timeStps[cur_t] + [str(all_values[cur_t,iVec])]) + "\n")
|
204
|
-
|
258
|
+
logging.info("Writing polygon time series finished !")
|
205
259
|
|
206
260
|
print(are_present)
|
207
261
|
|
208
|
-
|
209
262
|
# def plot(self):
|
210
263
|
# pass
|
211
264
|
|
File without changes
|
@@ -0,0 +1,335 @@
|
|
1
|
+
import math
|
2
|
+
import numpy as np
|
3
|
+
from numba import jit
|
4
|
+
|
5
|
+
""" JIT is a decorator that tells Numba to compile this function using the Numba JIT compiler. """
|
6
|
+
|
7
|
+
@jit(nopython=True)
|
8
|
+
def A_from_h(h:float, diameter:float):
|
9
|
+
""" Compute the area of a circular segment from its height """
|
10
|
+
d = diameter / 2.0 - h
|
11
|
+
theta = math.acos(1.0 - 2.0 * h / diameter)
|
12
|
+
chord = math.sqrt(h * (diameter - h))
|
13
|
+
area = theta * diameter**2 / 4.0 - chord * d
|
14
|
+
|
15
|
+
return area
|
16
|
+
|
17
|
+
@jit(nopython=True)
|
18
|
+
def dichotomy_A2h(f, a:float, b:float, args, tol=1e-10, max_iter=1000):
|
19
|
+
""" Dichotomy algorithm to find the root of a function f between a and b.
|
20
|
+
The function f must be defined as f(x, *args) and must return a scalar.
|
21
|
+
The function must have a single root in the interval [a, b].
|
22
|
+
"""
|
23
|
+
def cond_fun(val):
|
24
|
+
a, b, i = val
|
25
|
+
return (b - a) > tol
|
26
|
+
|
27
|
+
def body_fun(val):
|
28
|
+
a, b, i = val
|
29
|
+
c = (a + b) / 2.
|
30
|
+
diameter = args[0]
|
31
|
+
fa = f(a, diameter)
|
32
|
+
fc = f(c, diameter)
|
33
|
+
if fc == 0:
|
34
|
+
return (c, c, i + 1)
|
35
|
+
else:
|
36
|
+
if fa * fc < 0:
|
37
|
+
return (a, c, i + 1)
|
38
|
+
else:
|
39
|
+
return (c, b, i + 1)
|
40
|
+
|
41
|
+
i=0
|
42
|
+
while cond_fun((a, b, i)) and i < max_iter:
|
43
|
+
a, b, i = body_fun((a, b, 0))
|
44
|
+
|
45
|
+
return (a + b) / 2
|
46
|
+
|
47
|
+
@jit(nopython=True)
|
48
|
+
def segment_of_circle(diameter:float, h:float=None, chord:float=None,
|
49
|
+
arc_length:float=None, area:float=None,
|
50
|
+
from_which:int=None, init_val:bool=None,
|
51
|
+
eps:float=1e-8) -> tuple:
|
52
|
+
""" Calcul des caractristiques d'un segment circulaire
|
53
|
+
plus d'infos sur http://mathworld.wolfram.com/CircularSegment.html.
|
54
|
+
|
55
|
+
:param diameter: diamtre du cercle [m]
|
56
|
+
:param h: hauteur du segment [m]
|
57
|
+
:param chord: longueur de la corde [m]
|
58
|
+
:param arc_length: longueur de l'arc soutenu par la corde [m]
|
59
|
+
:param area: aire du sgment [m]
|
60
|
+
:param from_which: variable de calcul sur base de laquelle les autres grandeurs doivent tre values [index dans l'ordre des paramètres (h = 1, area = 4...)]
|
61
|
+
:param init_val: utilise h comme valeur initiale pour le calcul de h depuis A [booléen]
|
62
|
+
"""
|
63
|
+
|
64
|
+
R = diameter / 2.0
|
65
|
+
|
66
|
+
if from_which == 1: # from h
|
67
|
+
# The solution is unique
|
68
|
+
|
69
|
+
d = diameter / 2.0 - h
|
70
|
+
theta = math.acos(1.0 - 2.0 * h / diameter)
|
71
|
+
|
72
|
+
arc_length = theta * diameter
|
73
|
+
chord = math.sqrt(h * (diameter - h))
|
74
|
+
area = theta * diameter**2 / 4.0 - chord * d
|
75
|
+
chord = 2.0 * chord
|
76
|
+
|
77
|
+
elif from_which == 2: # from chord
|
78
|
+
# The solution is not unique --> two possible values for h
|
79
|
+
# Conserve the value of h that is the closest to the previous value of h
|
80
|
+
|
81
|
+
# h1 as root of the quadratic equation
|
82
|
+
h1 = (diameter - math.sqrt(diameter**2 - chord**2)) / 2.0
|
83
|
+
|
84
|
+
if init_val is not None:
|
85
|
+
if init_val:
|
86
|
+
h2 = diameter - h1
|
87
|
+
dh1 = abs(h - h1)
|
88
|
+
dh2 = abs(h + h1 - diameter)
|
89
|
+
|
90
|
+
h = h1 if dh1 < dh2 else h2
|
91
|
+
else:
|
92
|
+
# Conserve the lowest value of h
|
93
|
+
h = h1
|
94
|
+
else:
|
95
|
+
h = h1
|
96
|
+
|
97
|
+
d = diameter / 2.0 - h
|
98
|
+
theta = math.acos(1.0 - 2.0 * h / diameter)
|
99
|
+
|
100
|
+
arc_length = theta * diameter
|
101
|
+
area = theta * diameter**2 / 4.0 - chord /2. * d
|
102
|
+
|
103
|
+
elif from_which == 3: # from arc_length
|
104
|
+
# The solution is unique
|
105
|
+
|
106
|
+
theta = arc_length / diameter
|
107
|
+
h = R * (1.0 - math.cos(theta))
|
108
|
+
d = R - h
|
109
|
+
|
110
|
+
chord = math.sqrt(h * (diameter - h))
|
111
|
+
area = theta * diameter**2 / 4.0 - chord * d
|
112
|
+
chord = 2.0 * chord
|
113
|
+
|
114
|
+
elif from_which in [4,41]: # from area using Newton's method
|
115
|
+
# The solution is unique BUT the calculation is iterative
|
116
|
+
|
117
|
+
cur_error = 1.0
|
118
|
+
|
119
|
+
d2by4 = diameter**2 / 4.0
|
120
|
+
area_max = math.pi * d2by4
|
121
|
+
|
122
|
+
if area == 0.0:
|
123
|
+
h = 0.0
|
124
|
+
chord = 0.0
|
125
|
+
arc_length = 0.0
|
126
|
+
|
127
|
+
elif area_max > area:
|
128
|
+
if init_val is not None:
|
129
|
+
if not init_val or h == 0.0:
|
130
|
+
h = R
|
131
|
+
else:
|
132
|
+
h = R
|
133
|
+
|
134
|
+
while abs(cur_error) > eps:
|
135
|
+
d = R - h
|
136
|
+
theta = math.acos(1.0 - h / R)
|
137
|
+
chord = math.sqrt(h * (diameter - h))
|
138
|
+
area_loc = theta * d2by4 - chord * d
|
139
|
+
dAdh = chord - ((h - R)**2 - d2by4) / (chord + 1e-200)
|
140
|
+
|
141
|
+
cur_error = (area_loc - area) / dAdh
|
142
|
+
if h - cur_error < 0.0:
|
143
|
+
h = h / 2.0
|
144
|
+
elif h - cur_error > diameter:
|
145
|
+
h = (h + diameter) / 2.0
|
146
|
+
else:
|
147
|
+
h = h - cur_error
|
148
|
+
|
149
|
+
chord = 2.0 * chord
|
150
|
+
arc_length = theta * diameter
|
151
|
+
|
152
|
+
else:
|
153
|
+
h = diameter
|
154
|
+
chord = 0.0
|
155
|
+
arc_length = math.pi * diameter
|
156
|
+
|
157
|
+
elif from_which == 42: # from area but using dichotomy rather than Newton-Raphson
|
158
|
+
# The solution is unique BUT the calculation is iterative
|
159
|
+
|
160
|
+
cur_error = 1.0
|
161
|
+
|
162
|
+
d2by4 = diameter**2 / 4.0
|
163
|
+
area_max = math.pi * d2by4
|
164
|
+
|
165
|
+
if area == 0.0:
|
166
|
+
h = 0.0
|
167
|
+
chord = 0.0
|
168
|
+
arc_length = 0.0
|
169
|
+
|
170
|
+
elif area_max > area:
|
171
|
+
if init_val is not None:
|
172
|
+
if not init_val or h == 0.0:
|
173
|
+
h = R
|
174
|
+
else:
|
175
|
+
h = R
|
176
|
+
|
177
|
+
h = dichotomy_A2h(f=A_from_h, a=0., b=diameter, args=(diameter,), tol=eps)
|
178
|
+
|
179
|
+
d = diameter / 2.0 - h
|
180
|
+
theta = math.acos(1.0 - 2.0 * h / diameter)
|
181
|
+
arc_length = theta * diameter
|
182
|
+
chord = math.sqrt(h * (diameter - h))
|
183
|
+
chord = 2.0 * chord
|
184
|
+
|
185
|
+
else:
|
186
|
+
h = diameter
|
187
|
+
chord = 0.0
|
188
|
+
arc_length = math.pi * diameter
|
189
|
+
|
190
|
+
return diameter, h, chord, arc_length, area
|
191
|
+
|
192
|
+
|
193
|
+
if __name__ == '__main__':
|
194
|
+
|
195
|
+
diameter = 10.0
|
196
|
+
h = 5.0
|
197
|
+
chord = -1.
|
198
|
+
arc_length = -1.
|
199
|
+
area = -1.
|
200
|
+
from_which = 1
|
201
|
+
init_val = None
|
202
|
+
|
203
|
+
res1 = segment_of_circle(diameter, h, chord, arc_length, area, from_which, init_val)
|
204
|
+
diameter, h, chord, arc_length, area = res1
|
205
|
+
|
206
|
+
print(f"diameter = {diameter}")
|
207
|
+
print(f"h = {h}")
|
208
|
+
print(f"chord = {chord}")
|
209
|
+
print(f"arc_length = {arc_length}")
|
210
|
+
print(f"area = {area}")
|
211
|
+
|
212
|
+
from_which = 2
|
213
|
+
res2 = segment_of_circle(diameter, h, chord, arc_length, area, from_which, init_val)
|
214
|
+
diameter, h, chord, arc_length, area = res2
|
215
|
+
|
216
|
+
print(f"diameter = {diameter}")
|
217
|
+
print(f"h = {h}")
|
218
|
+
print(f"chord = {chord}")
|
219
|
+
print(f"arc_length = {arc_length}")
|
220
|
+
print(f"area = {area}")
|
221
|
+
|
222
|
+
from_which = 2
|
223
|
+
res2 = segment_of_circle(diameter, h, chord/2., arc_length, area, from_which, False)
|
224
|
+
diameter, h, chord, arc_length, area = res2
|
225
|
+
|
226
|
+
print(f"diameter = {diameter}")
|
227
|
+
print(f"h = {h}")
|
228
|
+
print(f"chord = {chord}")
|
229
|
+
print(f"arc_length = {arc_length}")
|
230
|
+
print(f"area = {area}")
|
231
|
+
|
232
|
+
from_which = 3
|
233
|
+
res3 = segment_of_circle(diameter, h, chord, arc_length, area, from_which, init_val)
|
234
|
+
diameter, h, chord, arc_length, area = res3
|
235
|
+
|
236
|
+
print(f"diameter = {diameter}")
|
237
|
+
print(f"h = {h}")
|
238
|
+
print(f"chord = {chord}")
|
239
|
+
print(f"arc_length = {arc_length}")
|
240
|
+
print(f"area = {area}")
|
241
|
+
|
242
|
+
from_which = 2
|
243
|
+
res2 = segment_of_circle(diameter, h, chord/2., arc_length, area, from_which, init_val)
|
244
|
+
diameter, h, chord, arc_length, area = res2
|
245
|
+
|
246
|
+
print(f"diameter = {diameter}")
|
247
|
+
print(f"h = {h}")
|
248
|
+
print(f"chord = {chord}")
|
249
|
+
print(f"arc_length = {arc_length}")
|
250
|
+
print(f"area = {area}")
|
251
|
+
|
252
|
+
diameter = 10.0
|
253
|
+
h = 1.
|
254
|
+
chord = -1.
|
255
|
+
arc_length = -1.
|
256
|
+
area = 10.0
|
257
|
+
from_which = 4
|
258
|
+
init_val = True
|
259
|
+
|
260
|
+
res4 = segment_of_circle(diameter, h, chord, arc_length, area, from_which, init_val)
|
261
|
+
diameter, h, chord, arc_length, area = res4
|
262
|
+
|
263
|
+
print(f"diameter = {diameter}")
|
264
|
+
print(f"h = {h}")
|
265
|
+
print(f"chord = {chord}")
|
266
|
+
print(f"arc_length = {arc_length}")
|
267
|
+
print(f"area = {area}")
|
268
|
+
|
269
|
+
diameter = 10.0
|
270
|
+
h = -1.
|
271
|
+
chord = -1.
|
272
|
+
arc_length = -1.
|
273
|
+
area = 10.0
|
274
|
+
from_which = 4
|
275
|
+
init_val = False
|
276
|
+
|
277
|
+
res5 = segment_of_circle(diameter, h, chord, arc_length, area, from_which, init_val)
|
278
|
+
diameter, h, chord, arc_length, area = res5
|
279
|
+
|
280
|
+
print(f"diameter = {diameter}")
|
281
|
+
print(f"h = {h}")
|
282
|
+
print(f"chord = {chord}")
|
283
|
+
print(f"arc_length = {arc_length}")
|
284
|
+
print(f"area = {area}")
|
285
|
+
|
286
|
+
diameter = 10.0
|
287
|
+
h = 9.
|
288
|
+
chord = -1.
|
289
|
+
arc_length = -1.
|
290
|
+
area = 10.0
|
291
|
+
from_which = 4
|
292
|
+
init_val = True
|
293
|
+
|
294
|
+
res6 = segment_of_circle(diameter, h, chord, arc_length, area, from_which, init_val)
|
295
|
+
diameter, h, chord, arc_length, area = res6
|
296
|
+
|
297
|
+
print(f"diameter = {diameter}")
|
298
|
+
print(f"h = {h}")
|
299
|
+
print(f"chord = {chord}")
|
300
|
+
print(f"arc_length = {arc_length}")
|
301
|
+
print(f"area = {area}")
|
302
|
+
|
303
|
+
diameter = 10.0
|
304
|
+
h = 2.
|
305
|
+
chord = -1.
|
306
|
+
arc_length = -1.
|
307
|
+
area = 10.0
|
308
|
+
from_which = 4 # from area using Newton's method
|
309
|
+
init_val = True
|
310
|
+
|
311
|
+
res7 = segment_of_circle(diameter, h, chord, arc_length, area, from_which, init_val, eps= 1e-12)
|
312
|
+
diameter, h, chord, arc_length, area = res7
|
313
|
+
|
314
|
+
print(f"diameter = {diameter}")
|
315
|
+
print(f"h = {h}")
|
316
|
+
print(f"chord = {chord}")
|
317
|
+
print(f"arc_length = {arc_length}")
|
318
|
+
print(f"area = {area}")
|
319
|
+
|
320
|
+
diameter = 10.0
|
321
|
+
h = 2.
|
322
|
+
chord = -1.
|
323
|
+
arc_length = -1.
|
324
|
+
area = 10.0
|
325
|
+
from_which = 42 # from area using dichotomy
|
326
|
+
init_val = True
|
327
|
+
|
328
|
+
res8 = segment_of_circle(diameter, h, chord, arc_length, area, from_which, init_val, eps= 1e-12)
|
329
|
+
diameter, h, chord, arc_length, area = res7
|
330
|
+
|
331
|
+
print(f"diameter = {diameter}")
|
332
|
+
print(f"h = {h}")
|
333
|
+
print(f"chord = {chord}")
|
334
|
+
print(f"arc_length = {arc_length}")
|
335
|
+
print(f"area = {area}")
|