topologicpy 0.6.0__py3-none-any.whl → 0.6.2__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/Aperture.py CHANGED
@@ -34,7 +34,8 @@ class Aperture(topologic.Aperture):
34
34
  The topology of the input aperture.
35
35
 
36
36
  """
37
- if not isinstance(aperture, topologic.Aperture):
37
+ from topologicpy.Topology import Topology
38
+ if not Topology.IsInstance(aperture, "aperture"):
38
39
  print("Aperture.Topology - Error: The input aperture parameter is not a valid topologic aperture. Returning None.")
39
40
  return None
40
41
  return topologic.Aperture.Topology(aperture)
@@ -57,7 +58,8 @@ class Aperture(topologic.Aperture):
57
58
  The created aperture.
58
59
 
59
60
  """
60
- if not isinstance(topology, topologic.Topology):
61
+ from topologicpy.Topology import Topology
62
+ if not Topology.IsInstance(topology, "topology"):
61
63
  print("Aperture.ByTopologyContext - Error: The input topology parameter is not a valid topologic topology. Returning None.")
62
64
  return None
63
65
  if not isinstance(context, topologic.Context):
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,873 @@
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
+ import topologic_core as topologic
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
+ from topologicpy.Dictionary import Dictionary
591
+ if origin == None:
592
+ origin = Vertex.Origin()
593
+ if startTime == None:
594
+ startTime = Sun.Sunrise(latitude=latitude, longitude=longitude, date=date)
595
+ if endTime == None:
596
+ endTime = Sun.Sunset(latitude=latitude, longitude=longitude, date=date)
597
+ vertices = Sun.VerticesByDate(latitude=latitude, longitude=longitude, date=date,
598
+ startTime=startTime, endTime=endTime, interval=interval,
599
+ origin=origin, radius=radius, north=north)
600
+ if len(vertices) < 2:
601
+ return None
602
+ wire = Wire.ByVertices(vertices, close=False)
603
+ if not sides == None:
604
+ vertices = []
605
+ for i in range(sides):
606
+ u = float(i)/float(sides)
607
+ v = Wire.VertexByParameter(wire, u)
608
+ vertices.append(v)
609
+ wire = Wire.ByVertices(vertices, close=False)
610
+ d = Dictionary.ByKeysValues(["latitude", "longitude", "date", "startTime", "endTime", "interval", "type"],
611
+ [latitude, longitude, str(date), str(startTime), str(endTime), interval, "date"])
612
+ wire = Topology.SetDictionary(wire, d)
613
+ return wire
614
+
615
+ @staticmethod
616
+ def VerticesByHour(latitude, longitude, hour, startDay=1, endDay=365, interval=5, origin=None, radius=0.5, north=0):
617
+ """
618
+ Returns the sun locations based on the input parameters.
619
+
620
+ Parameters
621
+ ----------
622
+ latitude : float
623
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
624
+ longitude : float
625
+ The input longitude. See https://en.wikipedia.org/wiki/Longitude.
626
+ hour : datetime
627
+ The input hour.
628
+ startDay : integer , optional
629
+ The desired start day to compute the sun location. The default is 1.
630
+ endDay : integer , optional
631
+ The desired end day to compute the sun location. The default is 365.
632
+ interval : int , optional
633
+ The interval in days to compute the sun location. The default is 5.
634
+ origin : topologic.Vertex , optional
635
+ The desired origin of the world. If set to None, the origin will be set to (0,0,0). The default is None.
636
+ radius : float , optional
637
+ The desired radius of the sun orbit. The default is 0.5.
638
+ north : float, optional
639
+ The desired compass angle of the north direction. The default is 0 which points in the positive Y-axis direction.
640
+
641
+ Returns
642
+ -------
643
+ list
644
+ The sun locations represented as a list of vertices.
645
+ """
646
+ from datetime import datetime
647
+ from datetime import timedelta
648
+ def day_of_year_to_datetime(year, day_of_year):
649
+ # Construct a datetime object for the first day of the year
650
+ base_date = datetime(year, 1, 1)
651
+ # Add the number of days to get to the specified day of the year
652
+ target_date = base_date + timedelta(days=day_of_year - 1)
653
+ return target_date
654
+
655
+ now = datetime.now()
656
+ # Get the year component
657
+ year = now.year
658
+ vertices = []
659
+ for day_of_year in range(startDay, endDay, interval):
660
+ date = day_of_year_to_datetime(year, day_of_year)
661
+ date += timedelta(hours=hour)
662
+ v = Sun.Vertex(latitude=latitude, longitude=longitude, date=date, origin=origin, radius=radius, north=north)
663
+ vertices.append(v)
664
+ return vertices
665
+
666
+ @staticmethod
667
+ def PathByHour(latitude, longitude, hour, startDay=1, endDay=365, interval=5, origin=None, radius=0.5, sides=None, north=0):
668
+ """
669
+ Returns the sun locations based on the input parameters.
670
+
671
+ Parameters
672
+ ----------
673
+ latitude : float
674
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
675
+ longitude : float
676
+ The input longitude. See https://en.wikipedia.org/wiki/Longitude.
677
+ hour : datetime
678
+ The input hour.
679
+ startDay : integer , optional
680
+ The desired start day of the year to compute the sun location. The default is 1.
681
+ endDay : integer , optional
682
+ The desired end day of the year to compute the sun location. The default is 365.
683
+ interval : int , optional
684
+ The interval in days to compute the sun location. The default is 5.
685
+ origin : topologic.Vertex , optional
686
+ The desired origin of the world. If set to None, the origin will be set to (0,0,0). The default is None.
687
+ radius : float , optional
688
+ The desired radius of the sun orbit. The default is 0.5.
689
+ sides : int , optional
690
+ If set to None, the path is divided based on the interval. Otherwise, it is equally divided into the number of sides.
691
+ The default is None.
692
+ north : float, optional
693
+ The desired compass angle of the north direction. The default is 0 which points in the positive Y-axis direction.
694
+
695
+ Returns
696
+ -------
697
+ topologic.Wire
698
+ The sun path represented as a topologic wire.
699
+ """
700
+
701
+ from topologicpy.Wire import Wire
702
+ from topologicpy.Dictionary import Dictionary
703
+
704
+ vertices = Sun.VerticesByHour(latitude=latitude, longitude=longitude, hour=hour,
705
+ startDay=startDay, endDay=endDay, interval=interval,
706
+ origin=origin, radius=radius, north=north)
707
+ if len(vertices) < 2:
708
+ return None
709
+ wire = Wire.ByVertices(vertices, close=False)
710
+ if not sides == None:
711
+ vertices = []
712
+ for i in range(sides):
713
+ u = float(i)/float(sides)
714
+ v = Wire.VertexByParameter(wire, u)
715
+ vertices.append(v)
716
+ wire = Wire.ByVertices(vertices, close=True)
717
+ d = Dictionary.ByKeysValues(["latitude", "longitude", "hour", "startDay", "endDay", "interval", "type"],
718
+ [latitude, longitude, hour, startDay, endDay, interval, "hour"])
719
+ wire = Topology.SetDictionary(wire, d)
720
+ return wire
721
+
722
+ @staticmethod
723
+ def Diagram(latitude, longitude, minuteInterval=30, dayInterval=15,
724
+ origin=None, radius=0.5, uSides=180, vSides=180, north=0,
725
+ compass = False, shell=False):
726
+ """
727
+ Returns the sun diagram based on the input parameters. See https://hyperfinearchitecture.com/how-to-read-sun-path-diagrams/.
728
+
729
+ Parameters
730
+ ----------
731
+ latitude : float
732
+ The input latitude. See https://en.wikipedia.org/wiki/Latitude.
733
+ longitude : float
734
+ The input longitude. See https://en.wikipedia.org/wiki/Longitude.
735
+ minuteInterval : int , optional
736
+ The interval in minutes to compute the sun location for the date path. The default is 30.
737
+ dayInterval : int , optional
738
+ The interval in days for the hourly path to compute the sun location. The default is 15.
739
+ origin : topologic.Vertex , optional
740
+ The desired origin of the world. If set to None, the origin will be set to (0,0,0). The default is None.
741
+ radius : float , optional
742
+ The desired radius of the sun orbit. The default is 0.5.
743
+ uSides : int , optional
744
+ The number of sides to divide the diagram horizontally (along the azimuth). The default is 180.
745
+ vSides : int , optional
746
+ The number of sides to divide the diagram paths vertically (along the altitude). The default is 180.
747
+ north : float, optional
748
+ The desired compass angle of the north direction. The default is 0 which points in the positive Y-axis direction.
749
+ compass : bool , optional
750
+ If set to True, a compass (shell) is included. Othwerwise, it is is not.
751
+ shell : bool , optional
752
+ If set to True, the total surface (shell) of the sun paths is incldued. Otherwise, it is not.
753
+
754
+ Returns
755
+ -------
756
+ dict
757
+ A dictionary of the sun diagram shapes. The keys in this dictionary are:
758
+ - 'date_paths': These are the sun paths (wire) for the winter solstice, equinox, and summer solstice
759
+ - 'hourly_paths': These are the figure-8 (wire) for the sun location on the same hour on each selected day of the year.
760
+ - 'shell': This is the total surface (shell) of the sun paths. This is included only if the shell option is set to True.
761
+ - 'compass': This is the compass (shell) on the ground. It is made of 36 sides and 10 rings. This is included only
762
+ if the compass option is set to True.
763
+ - 'center' : This is a cross-shape (wire) at the center of the diagram. This is included only if the compass option is set to True.
764
+ - 'ground' : This is a circle (face) on the ground. It is made of 36 sides. This is included only if
765
+ the compass option is set to False.
766
+ """
767
+
768
+ from datetime import datetime
769
+ from datetime import timedelta
770
+ from topologicpy.Vertex import Vertex
771
+ from topologicpy.Edge import Edge
772
+ from topologicpy.Wire import Wire
773
+ from topologicpy.Shell import Shell
774
+ from topologicpy.Cell import Cell
775
+ from topologicpy.Cluster import Cluster
776
+ from topologicpy.Topology import Topology
777
+ from topologicpy.Dictionary import Dictionary
778
+
779
+ if origin == None:
780
+ origin = Vertex.Origin()
781
+
782
+ cutter = Cell.Prism(origin=origin, width=radius*4, length=radius*4, height=radius*2)
783
+ cutter = Topology.Rotate(cutter, origin=origin, angle=-north)
784
+ cutter = Topology.Translate(cutter, 0,0,-radius)
785
+ now = datetime.now()
786
+ year = now.year
787
+ diagram = {}
788
+ winter_solstice = Sun.WinterSolstice(latitude=latitude, year=year)
789
+ summer_solstice = Sun.SummerSolstice(latitude=latitude, year=year)
790
+ equinox = Sun.AutumnEquinox(latitude=latitude, year=year)
791
+ dates = [winter_solstice, equinox, summer_solstice]
792
+ date_paths = []
793
+ for date in dates:
794
+ startTime = Sun.Sunrise(latitude=latitude, longitude=longitude, date=date) - timedelta(hours=2)
795
+ endTime = Sun.Sunset(latitude=latitude, longitude=longitude, date=date) + timedelta(hours=2)
796
+ path = Sun.PathByDate(latitude=latitude, longitude=longitude, date=date,
797
+ startTime=startTime, endTime=endTime, interval=minuteInterval,
798
+ origin=origin, radius=radius, sides=uSides, north=north)
799
+ # Capture the path's dictionary to re-apply later
800
+ d = Topology.Dictionary(path)
801
+ # Clip the path to above ground level
802
+ path = Topology.Difference(path, cutter)
803
+ path = Topology.SetDictionary(path, d)
804
+ date_paths.append(path)
805
+ diagram['date_paths'] = date_paths
806
+ # Hourly paths
807
+ hourly_paths = []
808
+ for hour in range (0, 24, 1):
809
+ hourly_path = Sun.PathByHour(latitude, longitude, hour, startDay=0, endDay=365, interval=dayInterval,
810
+ origin=origin, radius=radius, sides=vSides*2, north=north)
811
+ d = Topology.Dictionary(hourly_path)
812
+ hourly_path = Topology.Difference(hourly_path, cutter)
813
+ if Topology.IsInstance(hourly_path, "topology"):
814
+ hourly_path = Topology.SetDictionary(hourly_path, d)
815
+ hourly_paths.append(hourly_path)
816
+ diagram['hourly_paths'] = hourly_paths
817
+ if shell:
818
+ shell_paths = []
819
+ dates = [summer_solstice]
820
+ delta = (winter_solstice - summer_solstice)/12
821
+ for i in range(1,12):
822
+ a_date = summer_solstice + delta*i
823
+ if abs(a_date - equinox) < timedelta(hours=24*5):
824
+ dates.append(equinox)
825
+ else:
826
+ dates.append(a_date)
827
+ dates.append(winter_solstice)
828
+ for date in dates:
829
+ startTime = Sun.Sunrise(latitude=latitude, longitude=longitude, date=date) - timedelta(hours=2)
830
+ endTime = Sun.Sunset(latitude=latitude, longitude=longitude, date=date) + timedelta(hours=2)
831
+ shell_path = Sun.PathByDate(latitude=latitude, longitude=longitude, date=date,
832
+ startTime=startTime, endTime=endTime, interval=minuteInterval,
833
+ origin=origin, radius=radius, sides=uSides, north=north)
834
+ # Clip the path to above ground level
835
+ shell_path = Topology.Difference(shell_path, cutter)
836
+ path_vertices = []
837
+ for i in range(uSides+1):
838
+ u = float(i)/float(uSides)
839
+ v = Wire.VertexByParameter(shell_path, u)
840
+ path_vertices.append(v)
841
+ shell_path = Wire.ByVertices(path_vertices, close=False)
842
+ shell_paths.append(shell_path)
843
+ a_shell = Shell.ByWires(shell_paths, triangulate=True, silent=True)
844
+ d = Dictionary.ByKeysValues(["latitude", "longitude", "type"], [latitude, longitude, "shell"])
845
+ a_shell = Topology.SetDictionary(a_shell, d)
846
+ diagram['shell']= a_shell
847
+ else:
848
+ diagram['shell'] = None
849
+
850
+ if compass:
851
+ compass = Shell.Pie(origin=origin, radiusA=radius, radiusB=radius*0.1, sides=36, rings=10)
852
+ d = Dictionary.ByKeysValues(["latitude", "longitude", "type"], [latitude, longitude, "compass"])
853
+ compass = Topology.SetDictionary(compass, d)
854
+ diagram['compass'] = compass
855
+ edges = []
856
+ for i in range(0, 4, 1):
857
+ v2 = Topology.Translate(origin, 0, radius/float(9), 0)
858
+ edge = Edge.ByVertices(origin, v2)
859
+ edge = Topology.Rotate(edge, origin=origin, angle=90*i)
860
+ edge = Topology.Rotate(edge, origin=origin, angle=-north)
861
+ edges.append(edge)
862
+ center = Topology.SelfMerge(Cluster.ByTopologies(edges))
863
+ d = Dictionary.ByKeysValues(["latitude", "longitude", "type"], [latitude, longitude, "center"])
864
+ center = Topology.SetDictionary(center, d)
865
+ diagram['center'] = center
866
+ else:
867
+ ground = Wire.Circle(origin=origin, radius=radius, sides=36)
868
+ d = Dictionary.ByKeysValues(["latitude", "longitude", "type"], [latitude, longitude, "ground"])
869
+ ground = Topology.SetDictionary(ground, d)
870
+ diagram['compass'] = None
871
+ diagram['center'] = None
872
+ diagram['ground']= ground
873
+ return diagram
topologicpy/Topology.py CHANGED
@@ -4440,6 +4440,7 @@ class Topology():
4440
4440
  "Graph"
4441
4441
  "Aperture"
4442
4442
  "Dictionary"
4443
+ "Context"
4443
4444
 
4444
4445
  Returns
4445
4446
  -------
@@ -4471,6 +4472,8 @@ class Topology():
4471
4472
  return isinstance(topology, topologic.Aperture)
4472
4473
  elif "dictionary" in type.lower():
4473
4474
  return isinstance(topology, topologic.Dictionary)
4475
+ elif "context" in type.lower():
4476
+ return isinstance(topology, topologic.Context)
4474
4477
  else:
4475
4478
  print("Topology.IsInstance - Error: The type input string is not a known topology type. Returning None.")
4476
4479
  return None
topologicpy/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '0.6.0'
1
+ __version__ = '0.6.2'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: topologicpy
3
- Version: 0.6.0
3
+ Version: 0.6.2
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
@@ -1,4 +1,4 @@
1
- topologicpy/Aperture.py,sha256=xEKYZHKGmis2XKA1GKCDUGyXnpnrDMOXzQFzKsBZU10,2765
1
+ topologicpy/Aperture.py,sha256=Mp3ntv28UrBjeAxcaOpOWxM7fTrtFGTGl1314BRgBHU,2867
2
2
  topologicpy/Cell.py,sha256=2KSE-BnciiJKgA6mftsEmeLC-OjzriOmdzlEuoIWsh0,96552
3
3
  topologicpy/CellComplex.py,sha256=5tqj4kZKzESdqPHNrmfYV7i3g5trcXpiC9HpeqYwTn8,46270
4
4
  topologicpy/Cluster.py,sha256=un3waRSZf9tSkLSqItvCD6FypzNcKWcw38pocTlNKoI,54594
@@ -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/Topology.py,sha256=sAKa6tpjg2zA_hg9j5I2WRfYvVE7YXs_We0YytVAJZk,304811
22
+ topologicpy/Sun.py,sha256=jUokWlwlRaPFa3wC2-flIpE9gBae0YYSP73N_41VsNQ,36723
23
+ topologicpy/Topology.py,sha256=dE0LbZwPGQyzZYYZqN1W2FwszPEDTXIIXpkOFgRD2kw,304932
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=gMDttCkJF3h8Jr3eq_8NuJj26-9xyjg-YjR2bSNcGxM,22
29
+ topologicpy-0.6.2.dist-info/LICENSE,sha256=TfPDBt3ar0uv_f9cqCDMZ5rIzW3CY8anRRd4PkL6ejs,34522
30
+ topologicpy-0.6.2.dist-info/METADATA,sha256=OqDWsF7OV8X8rORRAY9ieKqPVhtHTImgj-MyXbyIy7M,46950
31
+ topologicpy-0.6.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
32
+ topologicpy-0.6.2.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
33
+ topologicpy-0.6.2.dist-info/RECORD,,