topologicpy 0.6.0__py3-none-any.whl → 0.6.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.
topologicpy/Face.py CHANGED
@@ -756,7 +756,7 @@ class Face(Topology):
756
756
  elif placement.lower() == "upperright":
757
757
  arrow = Topology.Translate(arrow, -radius, -radius, 0)
758
758
  arrow = Topology.Place(arrow, originA=Vertex.Origin(), originB=origin)
759
- arrow = Topology.Orient(arrow, orign=origin, direction=direction)
759
+ arrow = Topology.Orient(arrow, origin=origin, direction=direction)
760
760
  return arrow
761
761
 
762
762
  @staticmethod
topologicpy/Sun.py ADDED
@@ -0,0 +1,839 @@
1
+ # Copyright (C) 2024
2
+ # Wassim Jabi <wassim.jabi@gmail.com>
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify it under
5
+ # the terms of the GNU Affero General Public License as published by the Free Software
6
+ # Foundation, either version 3 of the License, or (at your option) any later
7
+ # version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful, but WITHOUT
10
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
12
+ # details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License along with
15
+ # this program. If not, see <https://www.gnu.org/licenses/>.
16
+
17
+ import os
18
+ import warnings
19
+
20
+ try:
21
+ import ephem
22
+ except:
23
+ print("Sun - Installing required ephem library.")
24
+ try:
25
+ os.system("pip install ephem")
26
+ except:
27
+ os.system("pip install ephem --user")
28
+ try:
29
+ import ephem
30
+ print("Sun - ephem library installed successfully.")
31
+ except:
32
+ warnings.warn("Sun - Error: Could not import ephem.")
33
+
34
+ class Sun():
35
+ @staticmethod
36
+ def WinterSolstice(latitude, year=None):
37
+ """
38
+ Returns the winter solstice date for the input latitude and year. See https://en.wikipedia.org/wiki/Winter_solstice.
39
+
40
+ Parameters
41
+ ----------
42
+ latitude : float
43
+ The input latitude.
44
+ year : integer , optional
45
+ The input year. The default is the current year.
46
+
47
+ Returns
48
+ -------
49
+ datetime
50
+ The datetime of the winter solstice
51
+
52
+ """
53
+ import os
54
+ import warnings
55
+ try:
56
+ import ephem
57
+ except:
58
+ print("Sun.WinterSolstice - Information: Installing required ephem library.")
59
+ try:
60
+ os.system("pip install ephem")
61
+ except:
62
+ os.system("pip install ephem --user")
63
+ try:
64
+ import ephem
65
+ print("Sun.WinterSolstice - Infromation: ephem library installed correctly.")
66
+ except:
67
+ warnings.warn("Sun.WinterSolstice - Error: Could not import ephem. Please try to install ephem manually. Returning None.")
68
+ return None
69
+ from datetime import datetime
70
+ if year == None:
71
+ year = datetime.now().year
72
+ if latitude >= 0:
73
+ solstice = ephem.next_solstice(ephem.Date(f"{year}/12/1"))
74
+ else:
75
+ solstice = ephem.next_solstice(ephem.Date(f"{year}/6/1"))
76
+ return solstice.datetime()
77
+
78
+ @staticmethod
79
+ def SummerSolstice(latitude, year):
80
+ """
81
+ Returns the winter solstice date for the input latitude and year. See https://en.wikipedia.org/wiki/Summer_solstice.
82
+
83
+ Parameters
84
+ ----------
85
+ latitude : float
86
+ The input latitude.
87
+ year : integer , optional
88
+ The input year. The default is the current year.
89
+
90
+ Returns
91
+ -------
92
+ datetime
93
+ The datetime of the summer solstice
94
+
95
+ """
96
+ import os
97
+ import warnings
98
+ try:
99
+ import ephem
100
+ except:
101
+ print("Sun.SummerSolstice - Information: Installing required ephem library.")
102
+ try:
103
+ os.system("pip install ephem")
104
+ except:
105
+ os.system("pip install ephem --user")
106
+ try:
107
+ import ephem
108
+ print("Sun.SummerSolstice - Infromation: ephem library installed correctly.")
109
+ except:
110
+ warnings.warn("Sun.SummerSolstice - Error: Could not import ephem. Please try to install ephem manually. Returning None.")
111
+ return None
112
+
113
+ if latitude >= 0:
114
+ solstice = ephem.next_solstice(ephem.Date(f"{year}/6/1"))
115
+ else:
116
+ solstice = ephem.next_solstice(ephem.Date(f"{year}/12/1"))
117
+ return solstice.datetime()
118
+
119
+ @staticmethod
120
+ def SpringEquinox(latitude, year):
121
+ """
122
+ Returns the spring (vernal) equinox date for the input latitude and year. See https://en.wikipedia.org/wiki/March_equinox.
123
+
124
+ Parameters
125
+ ----------
126
+ latitude : float
127
+ The input latitude.
128
+ year : integer , optional
129
+ The input year. The default is the current year.
130
+
131
+ Returns
132
+ -------
133
+ datetime
134
+ The datetime of the summer solstice
135
+ """
136
+ import os
137
+ import warnings
138
+ try:
139
+ import ephem
140
+ except:
141
+ print("Sun.SpringEquinox - Information: Installing required ephem library.")
142
+ try:
143
+ os.system("pip install ephem")
144
+ except:
145
+ os.system("pip install ephem --user")
146
+ try:
147
+ import ephem
148
+ print("Sun.SpringEquinox - Infromation: ephem library installed correctly.")
149
+ except:
150
+ warnings.warn("Sun.SpringEquinox - Error: Could not import ephem. Please try to install ephem manually. Returning None.")
151
+ return None
152
+
153
+ if latitude >= 0:
154
+ equinox = ephem.next_equinox(ephem.Date(f"{year}/3/1"))
155
+ else:
156
+ equinox = ephem.next_equinox(ephem.Date(f"{year}/9/1"))
157
+ return equinox.datetime()
158
+
159
+ @staticmethod
160
+ def AutumnEquinox(latitude, year):
161
+ """
162
+ Returns the autumnal equinox date for the input latitude and year. See https://en.wikipedia.org/wiki/September_equinox.
163
+
164
+ Parameters
165
+ ----------
166
+ latitude : float
167
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
168
+ year : integer , optional
169
+ The input year. The default is the current year.
170
+
171
+ Returns
172
+ -------
173
+ datetime
174
+ The datetime of the summer solstice
175
+ """
176
+ import os
177
+ import warnings
178
+ try:
179
+ import ephem
180
+ except:
181
+ print("Sun.AutumnEquinox - Information: Installing required ephem library.")
182
+ try:
183
+ os.system("pip install ephem")
184
+ except:
185
+ os.system("pip install ephem --user")
186
+ try:
187
+ import ephem
188
+ print("Sun.AutumnEquinox - Infromation: ephem library installed correctly.")
189
+ except:
190
+ warnings.warn("Sun.AutumnEquinox - Error: Could not import ephem. Please try to install ephem manually. Returning None.")
191
+ return None
192
+
193
+ if latitude >= 0:
194
+ equinox = ephem.next_equinox(ephem.Date(f"{year}/9/1"))
195
+ else:
196
+ equinox = ephem.next_equinox(ephem.Date(f"{year}/3/1"))
197
+ return equinox.datetime()
198
+
199
+ @staticmethod
200
+ def Azimuth(latitude, longitude, date):
201
+ """
202
+ Returns the Azimuth angle. See https://en.wikipedia.org/wiki/Azimuth.
203
+
204
+ Parameters
205
+ ----------
206
+ latitude : float
207
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
208
+ longitude : float
209
+ The input longitude. See https://en.wikipedia.org/wiki/Longitude.
210
+ date : datetime
211
+ The input datetime.
212
+
213
+ Returns
214
+ -------
215
+ float
216
+ The azimuth angle.
217
+ """
218
+ import os
219
+ import warnings
220
+ import math
221
+ try:
222
+ import ephem
223
+ except:
224
+ print("Sun.Azimuth - Information: Installing required ephem library.")
225
+ try:
226
+ os.system("pip install ephem")
227
+ except:
228
+ os.system("pip install ephem --user")
229
+ try:
230
+ import ephem
231
+ print("Sun.Azimuth - Infromation: ephem library installed correctly.")
232
+ except:
233
+ warnings.warn("Sun.Azimuth - Error: Could not import ephem. Please try to install ephem manually. Returning None.")
234
+ return None
235
+
236
+ observer = ephem.Observer()
237
+ observer.date = date
238
+ observer.lat = str(latitude)
239
+ observer.lon = str(longitude)
240
+ sun = ephem.Sun(observer)
241
+ sun.compute(observer)
242
+ azimuth = math.degrees(sun.az)
243
+ return azimuth
244
+
245
+ @staticmethod
246
+ def Altitude(latitude, longitude, date):
247
+ """
248
+ Returns the Altitude angle. See https://en.wikipedia.org/wiki/Altitude.
249
+
250
+ Parameters
251
+ ----------
252
+ latitude : float
253
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
254
+ longitude : float
255
+ The input longitude. See https://en.wikipedia.org/wiki/Longitude.
256
+ date : datetime
257
+ The input datetime.
258
+
259
+ Returns
260
+ -------
261
+ float
262
+ The altitude angle.
263
+ """
264
+ import os
265
+ import warnings
266
+ import math
267
+ try:
268
+ import ephem
269
+ except:
270
+ print("Sun.Altitude - Information: Installing required ephem library.")
271
+ try:
272
+ os.system("pip install ephem")
273
+ except:
274
+ os.system("pip install ephem --user")
275
+ try:
276
+ import ephem
277
+ print("Sun.Altitude - Infromation: ephem library installed correctly.")
278
+ except:
279
+ warnings.warn("Sun.Altitude - Error: Could not import ephem. Please try to install ephem manually. Returning None.")
280
+ return None
281
+
282
+ observer = ephem.Observer()
283
+ observer.date = date
284
+ observer.lat = str(latitude)
285
+ observer.lon = str(longitude)
286
+ sun = ephem.Sun(observer)
287
+ sun.compute(observer)
288
+ altitude = math.degrees(sun.alt)
289
+ return altitude
290
+
291
+ @staticmethod
292
+ def Sunrise(latitude, longitude, date):
293
+ """
294
+ Returns the Sunrise datetime.
295
+
296
+ Parameters
297
+ ----------
298
+ latitude : float
299
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
300
+ longitude : float
301
+ The input longitude. See https://en.wikipedia.org/wiki/Longitude.
302
+ date : datetime
303
+ The input datetime.
304
+
305
+ Returns
306
+ -------
307
+ datetime
308
+ The Sunrise datetime.
309
+ """
310
+
311
+ import os
312
+ import warnings
313
+ try:
314
+ import ephem
315
+ except:
316
+ print("Sun.Sunrise - Information: Installing required ephem library.")
317
+ try:
318
+ os.system("pip install ephem")
319
+ except:
320
+ os.system("pip install ephem --user")
321
+ try:
322
+ import ephem
323
+ print("Sun.Sunrise - Infromation: ephem library installed correctly.")
324
+ except:
325
+ warnings.warn("Sun.Sunrise - Error: Could not import ephem. Please try to install ephem manually. Returning None.")
326
+ return None
327
+
328
+ date = date.replace(hour=12, minute=0, second=0, microsecond=0)
329
+ observer = ephem.Observer()
330
+ observer.lat = str(latitude)
331
+ observer.lon = str(longitude)
332
+ observer.date = date
333
+ sunrise = observer.previous_rising(ephem.Sun()).datetime()
334
+ return sunrise
335
+
336
+ @staticmethod
337
+ def Sunset(latitude, longitude, date):
338
+ """
339
+ Returns the Sunset datetime.
340
+
341
+ Parameters
342
+ ----------
343
+ latitude : float
344
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
345
+ longitude : float
346
+ The input longitude. See https://en.wikipedia.org/wiki/Longitude.
347
+ date : datetime
348
+ The input datetime.
349
+
350
+ Returns
351
+ -------
352
+ datetime
353
+ The Sunset datetime.
354
+ """
355
+
356
+ import os
357
+ import warnings
358
+ try:
359
+ import ephem
360
+ except:
361
+ print("Sun.Sunset - Information: Installing required ephem library.")
362
+ try:
363
+ os.system("pip install ephem")
364
+ except:
365
+ os.system("pip install ephem --user")
366
+ try:
367
+ import ephem
368
+ print("Sun.Sunset - Infromation: ephem library installed correctly.")
369
+ except:
370
+ warnings.warn("Sun.Sunset - Error: Could not import ephem. Please try to install ephem manually. Returning None.")
371
+ return None
372
+
373
+ date = date.replace(hour=12, minute=0, second=0, microsecond=0)
374
+ observer = ephem.Observer()
375
+ observer.lat = str(latitude)
376
+ observer.lon = str(longitude)
377
+ observer.date = date
378
+ sunset = observer.next_setting(ephem.Sun()).datetime()
379
+ return sunset
380
+
381
+ @staticmethod
382
+ def Vector(latitude, longitude, date, north=0):
383
+ """
384
+ Returns the Sun as a vector.
385
+
386
+ Parameters
387
+ ----------
388
+ latitude : float
389
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
390
+ longitude : float
391
+ The input longitude. See https://en.wikipedia.org/wiki/Longitude.
392
+ date : datetime
393
+ The input datetime.
394
+ north : float, optional
395
+ The desired compass angle of the north direction. The default is 0 which points in the positive Y-axis direction.
396
+
397
+ Returns
398
+ -------
399
+ list
400
+ The sun vector pointing from the location of the sun towards the origin.
401
+ """
402
+ from topologicpy.Vector import Vector
403
+ azimuth = Sun.Azimuth(latitude=latitude, longitude=longitude, date=date)
404
+ altitude = Sun.Altitude(latitude=latitude, longitude=longitude, date=date)
405
+ return Vector.ByAzimuthAltitude(azimuth=azimuth, altitude=altitude, north=north, reverse=True)
406
+
407
+ @staticmethod
408
+ def Position(latitude, longitude, date, origin=None, radius=0.5, north=0, mantissa=6):
409
+ """
410
+ Returns the Sun as a position ([X,Y,Z]).
411
+
412
+ Parameters
413
+ ----------
414
+ latitude : float
415
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
416
+ longitude : float
417
+ The input longitude. See https://en.wikipedia.org/wiki/Longitude.
418
+ date : datetime
419
+ The input datetime.
420
+ origin : topologic.Vertex , optional
421
+ The desired origin of the world. If set to None, the origin will be set to (0,0,0). The default is None.
422
+ radius : float , optional
423
+ The desired radius of the sun orbit. The default is 0.5.
424
+ north : float, optional
425
+ The desired compass angle of the north direction. The default is 0 which points in the positive Y-axis direction.
426
+ mantissa : int , optional
427
+ The desired length of the mantissa. The default is 6.
428
+
429
+
430
+ Returns
431
+ -------
432
+ topologic.Vertex
433
+ The sun represented as a vertex.
434
+ """
435
+ from topologicpy.Vertex import Vertex
436
+ sun_v = Sun.Vertex(latitude=latitude, longitude=longitude, date=date, origin=origin, radius=radius, north=north)
437
+ return Vertex.Coordinates(sun_v, mantissa=mantissa)
438
+
439
+ @staticmethod
440
+ def Vertex(latitude, longitude, date, origin=None, radius=0.5, north=0):
441
+ """
442
+ Returns the Sun as a vertex.
443
+
444
+ Parameters
445
+ ----------
446
+ latitude : float
447
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
448
+ longitude : float
449
+ The input longitude. See https://en.wikipedia.org/wiki/Longitude.
450
+ date : datetime
451
+ The input datetime.
452
+ origin : topologic.Vertex , optional
453
+ The desired origin of the world. If set to None, the origin will be set to (0,0,0). The default is None.
454
+ radius : float , optional
455
+ The desired radius of the sun orbit. The default is 0.5.
456
+ north : float, optional
457
+ The desired compass angle of the north direction. The default is 0 which points in the positive Y-axis direction.
458
+
459
+ Returns
460
+ -------
461
+ topologic.Vertex
462
+ The sun represented as a vertex.
463
+ """
464
+ from topologicpy.Vertex import Vertex
465
+ from topologicpy.Topology import Topology
466
+ from topologicpy.Vector import Vector
467
+
468
+ if origin == None:
469
+ origin = Vertex.Origin()
470
+ vector = Vector.Reverse(Sun.Vector(latitude=latitude, longitude=longitude, date=date, north=north))
471
+ sun_v = Topology.TranslateByDirectionDistance(origin, direction=vector, distance=radius)
472
+ return sun_v
473
+
474
+ @staticmethod
475
+ def Edge(latitude, longitude, date, origin=None, radius=0.5, north=0):
476
+ """
477
+ Returns the Sun as a vector.
478
+
479
+ Parameters
480
+ ----------
481
+ latitude : float
482
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
483
+ longitude : float
484
+ The input longitude. See https://en.wikipedia.org/wiki/Longitude.
485
+ date : datetime
486
+ The input datetime.
487
+ origin : topologic.Vertex , optional
488
+ The desired origin of the world. If set to None, the origin will be set to (0,0,0). The default is None.
489
+ radius : float , optional
490
+ The desired radius of the sun orbit. The default is 0.5.
491
+ north : float, optional
492
+ The desired compass angle of the north direction. The default is 0 which points in the positive Y-axis direction.
493
+
494
+ Returns
495
+ -------
496
+ topologic.Edge
497
+ The sun represented as an edge pointing from the location of the sun towards the origin.
498
+ """
499
+ from topologicpy.Vertex import Vertex
500
+ from topologicpy.Edge import Edge
501
+ from topologicpy.Topology import Topology
502
+ from topologicpy.Vector import Vector
503
+
504
+ if origin == None:
505
+ origin = Vertex.Origin()
506
+ vector = Vector.Reverse(Sun.Vector(latitude=latitude, longitude=longitude, date=date, north=north))
507
+ sun_v = Topology.TranslateByDirectionDistance(origin, direction=vector, distance=radius)
508
+ edge = Edge.ByVertices(sun_v, origin)
509
+ return edge
510
+
511
+ @staticmethod
512
+ def VerticesByDate(latitude, longitude, date, startTime=None, endTime=None, interval=60, origin=None, radius=0.5, north=0):
513
+ """
514
+ Returns the Sun locations as vertices based on the input parameters.
515
+
516
+ Parameters
517
+ ----------
518
+ latitude : float
519
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
520
+ longitude : float
521
+ The input longitude. See https://en.wikipedia.org/wiki/Longitude.
522
+ date : datetime
523
+ The input datetime.
524
+ startTime : datetime , optional
525
+ The desired start time to compute the sun location. If set to None, Sun.Sunrise is used. The default is None.
526
+ endTime : datetime , optional
527
+ The desired end time to compute the sun location. If set to None, Sun.Sunset is used. The default is None.
528
+ interval : int , optional
529
+ The interval in minutes to compute the sun location. The default is 60.
530
+ origin : topologic.Vertex , optional
531
+ The desired origin of the world. If set to None, the origin will be set to (0,0,0). The default is None.
532
+ radius : float , optional
533
+ The desired radius of the sun orbit. The default is 0.5.
534
+ north : float, optional
535
+ The desired compass angle of the north direction. The default is 0 which points in the positive Y-axis direction.
536
+
537
+ Returns
538
+ -------
539
+ list
540
+ The sun locations represented as a list of vertices.
541
+ """
542
+ from datetime import timedelta
543
+ if startTime == None:
544
+ startTime = Sun.Sunrise(latitude=latitude, longitude=longitude, date=date)
545
+ if endTime == None:
546
+ endTime = Sun.Sunset(latitude=latitude, longitude=longitude, date=date)
547
+ vertices = []
548
+ current_time = startTime
549
+ while current_time <= endTime:
550
+ v = Sun.Vertex(latitude=latitude, longitude=longitude, date=current_time, origin=origin, radius=radius, north=north)
551
+ vertices.append(v)
552
+ current_time += timedelta(minutes=interval)
553
+ return vertices
554
+
555
+ @staticmethod
556
+ def PathByDate(latitude, longitude, date, startTime=None, endTime=None, interval=60, origin=None, radius=0.5, sides=None, north=0):
557
+ """
558
+ Returns the sun path based on the input parameters.
559
+
560
+ Parameters
561
+ ----------
562
+ latitude : float
563
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
564
+ longitude : float
565
+ The input longitude. See https://en.wikipedia.org/wiki/Longitude.
566
+ date : datetime
567
+ The input datetime.
568
+ startTime : datetime , optional
569
+ The desired start time to compute the sun location. If set to None, Sun.Sunrise is used. The default is None.
570
+ endTime : datetime , optional
571
+ The desired end time to compute the sun location. If set to None, Sun.Sunset is used. The default is None.
572
+ interval : int , optional
573
+ The interval in minutes to compute the sun location. The default is 60.
574
+ origin : topologic.Vertex , optional
575
+ The desired origin of the world. If set to None, the origin will be set to (0,0,0). The default is None.
576
+ radius : float , optional
577
+ The desired radius of the sun orbit. The default is 0.5.
578
+ sides : int , optional
579
+ If set to None, the path is divided based on the interval. Otherwise, it is equally divided into the number of sides.
580
+ The default is None.
581
+ north : float, optional
582
+ The desired compass angle of the north direction. The default is 0 which points in the positive Y-axis direction.
583
+
584
+ Returns
585
+ -------
586
+ topologic.Wire
587
+ The sun path represented as a wire.
588
+ """
589
+ from topologicpy.Wire import Wire
590
+ vertices = Sun.VerticesByDate(latitude=latitude, longitude=longitude, date=date,
591
+ startTime=startTime, endTime=endTime, interval=interval,
592
+ origin=origin, radius=radius, north=north)
593
+ if len(vertices) < 2:
594
+ return None
595
+ wire = Wire.ByVertices(vertices, close=False)
596
+ if not sides == None:
597
+ vertices = []
598
+ for i in range(sides):
599
+ u = float(i)/float(sides)
600
+ v = Wire.VertexByParameter(wire, u)
601
+ vertices.append(v)
602
+ wire = Wire.ByVertices(vertices, close=False)
603
+ return wire
604
+
605
+ @staticmethod
606
+ def VerticesByHour(latitude, longitude, hour, startDay=1, endDay=365, interval=5, origin=None, radius=0.5, north=0):
607
+ """
608
+ Returns the sun locations based on the input parameters.
609
+
610
+ Parameters
611
+ ----------
612
+ latitude : float
613
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
614
+ longitude : float
615
+ The input longitude. See https://en.wikipedia.org/wiki/Longitude.
616
+ hour : datetime
617
+ The input hour.
618
+ startDay : integer , optional
619
+ The desired start day to compute the sun location. The default is 1.
620
+ endDay : integer , optional
621
+ The desired end day to compute the sun location. The default is 365.
622
+ interval : int , optional
623
+ The interval in days to compute the sun location. The default is 5.
624
+ origin : topologic.Vertex , optional
625
+ The desired origin of the world. If set to None, the origin will be set to (0,0,0). The default is None.
626
+ radius : float , optional
627
+ The desired radius of the sun orbit. The default is 0.5.
628
+ north : float, optional
629
+ The desired compass angle of the north direction. The default is 0 which points in the positive Y-axis direction.
630
+
631
+ Returns
632
+ -------
633
+ list
634
+ The sun locations represented as a list of vertices.
635
+ """
636
+ from datetime import datetime
637
+ from datetime import timedelta
638
+ def day_of_year_to_datetime(year, day_of_year):
639
+ # Construct a datetime object for the first day of the year
640
+ base_date = datetime(year, 1, 1)
641
+ # Add the number of days to get to the specified day of the year
642
+ target_date = base_date + timedelta(days=day_of_year - 1)
643
+ return target_date
644
+
645
+ now = datetime.now()
646
+ # Get the year component
647
+ year = now.year
648
+ vertices = []
649
+ for day_of_year in range(startDay, endDay, interval):
650
+ date = day_of_year_to_datetime(year, day_of_year)
651
+ date += timedelta(hours=hour)
652
+ v = Sun.Vertex(latitude=latitude, longitude=longitude, date=date, origin=origin, radius=radius, north=north)
653
+ vertices.append(v)
654
+ return vertices
655
+
656
+ @staticmethod
657
+ def PathByHour(latitude, longitude, hour, startDay=1, endDay=365, interval=5, origin=None, radius=0.5, sides=None, north=0):
658
+ """
659
+ Returns the sun locations based on the input parameters.
660
+
661
+ Parameters
662
+ ----------
663
+ latitude : float
664
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
665
+ longitude : float
666
+ The input longitude. See https://en.wikipedia.org/wiki/Longitude.
667
+ hour : datetime
668
+ The input hour.
669
+ startDay : integer , optional
670
+ The desired start day to compute the sun location. The default is 1.
671
+ endDay : integer , optional
672
+ The desired end day to compute the sun location. The default is 365.
673
+ interval : int , optional
674
+ The interval in days to compute the sun location. The default is 5.
675
+ origin : topologic.Vertex , optional
676
+ The desired origin of the world. If set to None, the origin will be set to (0,0,0). The default is None.
677
+ radius : float , optional
678
+ The desired radius of the sun orbit. The default is 0.5.
679
+ sides : int , optional
680
+ If set to None, the path is divided based on the interval. Otherwise, it is equally divided into the number of sides.
681
+ The default is None.
682
+ north : float, optional
683
+ The desired compass angle of the north direction. The default is 0 which points in the positive Y-axis direction.
684
+
685
+ Returns
686
+ -------
687
+ topologic.Wire
688
+ The sun path represented as a topologic wire.
689
+ """
690
+
691
+ from topologicpy.Wire import Wire
692
+
693
+ vertices = Sun.VerticesByHour(latitude=latitude, longitude=longitude, hour=hour,
694
+ startDay=startDay, endDay=endDay, interval=interval,
695
+ origin=origin, radius=radius, north=north)
696
+ if len(vertices) < 2:
697
+ return None
698
+ wire = Wire.ByVertices(vertices, close=False)
699
+ if not sides == None:
700
+ vertices = []
701
+ for i in range(sides):
702
+ u = float(i)/float(sides)
703
+ v = Wire.VertexByParameter(wire, u)
704
+ vertices.append(v)
705
+ wire = Wire.ByVertices(vertices, close=True)
706
+ return wire
707
+
708
+ @staticmethod
709
+ def Diagram(latitude, longitude, minuteInterval=10, dayInterval=5,
710
+ origin=None, radius=0.5, uSides=180, vSides=180, north=0,
711
+ compass = False, shell=False):
712
+ """
713
+ Returns the sun diagram based on the input parameters. See https://hyperfinearchitecture.com/how-to-read-sun-path-diagrams/.
714
+
715
+ Parameters
716
+ ----------
717
+ latitude : float
718
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
719
+ longitude : float
720
+ The input longitude. See https://en.wikipedia.org/wiki/Longitude.
721
+ hour : datetime
722
+ The input hour.
723
+ minuteInterval : int , optional
724
+ The interval in minutes to compute the sun location. The default is 10.
725
+ dayInterval : int , optional
726
+ The interval in days to compute the sun location. The default is 5.
727
+ origin : topologic.Vertex , optional
728
+ The desired origin of the world. If set to None, the origin will be set to (0,0,0). The default is None.
729
+ radius : float , optional
730
+ The desired radius of the sun orbit. The default is 0.5.
731
+ uSides : int , optional
732
+ The number of sides to divide the diagram horizontally (along the azimuth). The default is 180.
733
+ vSides : int , optional
734
+ The number of sides to divide the diagram paths vertically (along the altitude). The default is 180.
735
+ north : float, optional
736
+ The desired compass angle of the north direction. The default is 0 which points in the positive Y-axis direction.
737
+ compass : bool , optional
738
+ If set to True, a compass is included. Othwerwise, it is is not.
739
+ shell : bool , optional
740
+ If set to True, a shell of the total surface of the sun paths is incldued. Otherwise, it is not.
741
+
742
+ Returns
743
+ -------
744
+ topologic.Cluster
745
+ The sun diagram.
746
+ """
747
+
748
+ from datetime import datetime
749
+ from datetime import timedelta
750
+ from topologicpy.Edge import Edge
751
+ from topologicpy.Wire import Wire
752
+ from topologicpy.Shell import Shell
753
+ from topologicpy.Cell import Cell
754
+ from topologicpy.Cluster import Cluster
755
+ from topologicpy.Topology import Topology
756
+
757
+ now = datetime.now()
758
+ year = now.year
759
+ objects = []
760
+ monthly_paths = []
761
+ winter_solstice = Sun.WinterSolstice(latitude=latitude, year=year)
762
+ summer_solstice = Sun.SummerSolstice(latitude=latitude, year=year)
763
+ equinox = Sun.SpringEquinox(latitude=latitude, year=year)
764
+ dates = [winter_solstice, equinox, summer_solstice]
765
+ for date in dates:
766
+ startTime = Sun.Sunrise(latitude=latitude, longitude=longitude, date=date) - timedelta(hours=1)
767
+ endTime = Sun.Sunset(latitude=latitude, longitude=longitude, date=date) + timedelta(hours=1)
768
+ path = Sun.PathByDate(latitude=latitude, longitude=longitude, date=date,
769
+ startTime=startTime, endTime=endTime, interval=minuteInterval,
770
+ origin=origin, radius=radius, sides=uSides, north=north)
771
+ monthly_paths.append(path)
772
+
773
+
774
+ hourly_paths = []
775
+ for hour in range (0, 24, 1):
776
+ hourly_path = Sun.PathByHour(latitude, longitude, hour, startDay=1, endDay=365, interval=dayInterval,
777
+ origin=origin, radius=radius, sides=vSides*2, north=north)
778
+ hourly_paths.append(hourly_path)
779
+ cutter = Cell.Prism(origin=origin, width=radius*4, length=radius*4, height=radius*4)
780
+ cutter = Topology.Rotate(cutter, origin=origin, angle=-north)
781
+ cutter = Topology.Translate(cutter, 0,0,-radius*2)
782
+ if shell:
783
+ shell_paths = [monthly_paths[0]]
784
+ for j in range(2,5,1):
785
+ if j == 3:
786
+ shell_paths.append(monthly_paths[1])
787
+ else:
788
+ date = (datetime(datetime.now().year, j, 21))
789
+ startTime = Sun.Sunrise(latitude=latitude, longitude=longitude, date=date) - timedelta(hours=1)
790
+ endTime = Sun.Sunset(latitude=latitude, longitude=longitude, date=date) + timedelta(hours=1)
791
+ shell_path = Sun.PathByDate(latitude=latitude, longitude=longitude, date=date,
792
+ startTime=startTime, endTime=endTime, interval=minuteInterval,
793
+ origin=origin, radius=radius, sides=uSides, north=north)
794
+ shell_paths.append(shell_path)
795
+ shell_paths.append(monthly_paths[-1])
796
+ print(len(shell_paths))
797
+ a_shell = Shell.ByWires(shell_paths, triangulate=True, silent=False)
798
+ a_shell = Topology.Difference(a_shell, cutter)
799
+ objects.append(a_shell)
800
+ if len(monthly_paths) > 1:
801
+ monthly_paths = Cluster.ByTopologies(monthly_paths)
802
+ else:
803
+ monthly_paths = monthly_paths[0]
804
+ monthly_paths = Topology.Difference(monthly_paths, cutter)
805
+ if len(hourly_paths) > 1:
806
+ hourly_paths = Cluster.ByTopologies(hourly_paths)
807
+ else:
808
+ hourly_paths = hourly_paths[0]
809
+ hourly_paths = Topology.Difference(hourly_paths, cutter)
810
+ objects += [monthly_paths, hourly_paths]
811
+ circle = Wire.Circle(origin=origin, radius=radius, sides=36)
812
+ circle = Topology.Rotate(circle, origin=origin, angle=-north)
813
+ objects.append(circle)
814
+ if compass:
815
+ radius_unit = radius/(float(9))
816
+ for i in range(1,9):
817
+ circle = Wire.Circle(origin=origin, radius=radius_unit*i, sides=36)
818
+ circle = Topology.Rotate(circle, origin=origin, angle=-north)
819
+ objects.append(circle)
820
+
821
+ edges = []
822
+ for i in range(0, 36, 1):
823
+ v1 = Topology.Translate(origin, 0, radius/float(9), 0)
824
+ v2 = Topology.Translate(origin, 0, radius, 0)
825
+ edge = Edge.ByVertices(v1, v2)
826
+ edge = Topology.Rotate(edge, origin=origin, angle=10*i)
827
+ edge = Topology.Rotate(edge, origin=origin, angle=-north)
828
+ edges.append(edge)
829
+ objects += edges
830
+ edges = []
831
+ for i in range(0, 4, 1):
832
+ v2 = Topology.Translate(origin, 0, radius/float(9), 0)
833
+ edge = Edge.ByVertices(origin, v2)
834
+ edge = Topology.Rotate(edge, origin=origin, angle=90*i)
835
+ edge = Topology.Rotate(edge, origin=origin, angle=-north)
836
+ edges.append(edge)
837
+ objects += edges
838
+ diag = Cluster.ByTopologies(objects)
839
+ return diag
topologicpy/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '0.6.0'
1
+ __version__ = '0.6.1'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: topologicpy
3
- Version: 0.6.0
3
+ Version: 0.6.1
4
4
  Summary: An Advanced Spatial Modelling and Analysis Software Library for Architecture, Engineering, and Construction.
5
5
  Author-email: Wassim Jabi <wassim.jabi@gmail.com>
6
6
  License: GNU AFFERO GENERAL PUBLIC LICENSE
@@ -8,7 +8,7 @@ topologicpy/DGL.py,sha256=Pk4hDjpXiWsA9yT304rfd-hMCwPxSOnCHbvp8u94wWE,138986
8
8
  topologicpy/Dictionary.py,sha256=R7Hb9-LTEgRyaRjxRn8NwBS1Hhkpcqe2QmHmKBxpr54,26243
9
9
  topologicpy/Edge.py,sha256=TEWb-zxZx57Fdzvdf92Y72MXi380NAvRCb8HS4YPtRU,49110
10
10
  topologicpy/EnergyModel.py,sha256=z83MPP641Sy8uTwH5lvfc0K90-d6BBCOnCebEMO152k,52759
11
- topologicpy/Face.py,sha256=s3SErim9RAsp5cbw8yWZEmNFIDy3ejX7zRj2so7MI9E,88675
11
+ topologicpy/Face.py,sha256=QcuICkzSuj4HDYQKH1jQl3X721pFIB1xd8S58x9HwNU,88676
12
12
  topologicpy/Graph.py,sha256=1i7qv_-AHLHpNFuX4Avv7rLgA1frQMariygv4_aL1Dw,365039
13
13
  topologicpy/Grid.py,sha256=8ARLeBUnEMQEwB2Xale928rZWeUBKYgerkmbvoSgnrs,17054
14
14
  topologicpy/Helper.py,sha256=07V9IFu5ilMpvAdZVhIbdBOjBJSRTtJ0BfR1IoRaRXU,17743
@@ -19,14 +19,15 @@ topologicpy/Plotly.py,sha256=DZbkrmjOr2c7uFHoWk6Uj2r54jCN_VDxzVMUcZagU18,94980
19
19
  topologicpy/Polyskel.py,sha256=MYHKFOQBlUNqoUhAdOcKRIHpSk0dWWVrZgXK34NkvFM,15936
20
20
  topologicpy/Shell.py,sha256=rnlnMRxY-KxJPpzr4oXy9m1I1QRQj1qhY8UXBgH8Pu8,74563
21
21
  topologicpy/Speckle.py,sha256=rUS6PCaxIjEF5_fUruxvMH47FMKg-ohcoU0qAUb-yNM,14267
22
+ topologicpy/Sun.py,sha256=tww8uxLYr_QxwUgqTGfvY_3zUoJUz7y4MDMwKzom2rI,33899
22
23
  topologicpy/Topology.py,sha256=sAKa6tpjg2zA_hg9j5I2WRfYvVE7YXs_We0YytVAJZk,304811
23
24
  topologicpy/Vector.py,sha256=apFuFOmi0WC3QWJ6O5LfLUyVvGOYWTTCTm26g3dKQrQ,29589
24
25
  topologicpy/Vertex.py,sha256=fHp2BarCGWiuJeMarDuLfSKGEqSFOulh7bd22siVl5A,64925
25
26
  topologicpy/Wire.py,sha256=sBYVsIj9QxEXOvNtjDqFaO2N2r1ZlairTn_HSW9rOiQ,128857
26
27
  topologicpy/__init__.py,sha256=D7ky87CAQMiS2KE6YLvcTLkTgA2PY7rASe6Z23pjp9k,872
27
- topologicpy/version.py,sha256=CBY3jsC-9HCm7eZ6CKD-sYLCejqOJ1pYWPQM4LGIXcI,22
28
- topologicpy-0.6.0.dist-info/LICENSE,sha256=TfPDBt3ar0uv_f9cqCDMZ5rIzW3CY8anRRd4PkL6ejs,34522
29
- topologicpy-0.6.0.dist-info/METADATA,sha256=_Aao-yAHvevdTDsBVbukMTSqt8sY7f5GMDUKKNDw8YA,46950
30
- topologicpy-0.6.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
31
- topologicpy-0.6.0.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
32
- topologicpy-0.6.0.dist-info/RECORD,,
28
+ topologicpy/version.py,sha256=gd3s3RotD0_KL90Tua-YkOr60Jm2C2_wvlEhAT08068,22
29
+ topologicpy-0.6.1.dist-info/LICENSE,sha256=TfPDBt3ar0uv_f9cqCDMZ5rIzW3CY8anRRd4PkL6ejs,34522
30
+ topologicpy-0.6.1.dist-info/METADATA,sha256=b1ojQGraQDFsgtIYwilIm927AnE0ODRn2EgamQ_nOKs,46950
31
+ topologicpy-0.6.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
32
+ topologicpy-0.6.1.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
33
+ topologicpy-0.6.1.dist-info/RECORD,,