3from typing
import Any, List
4from enum
import IntEnum
8 """Helios primitive type enumeration."""
19class int2(ctypes.Structure):
20 _fields_ = [(
'x', ctypes.c_int32), (
'y', ctypes.c_int32)]
23 return f
'int2({self.x}, {self.y})'
26 return f
'int2({self.x}, {self.y})'
29 """Create instance - only pass cls to prevent TypeError on Windows."""
30 return ctypes.Structure.__new__(cls)
34 if not isinstance(x, int):
35 raise ValueError(f
"int2.x must be an integer, got {type(x).__name__}: {x}")
36 if not isinstance(y, int):
37 raise ValueError(f
"int2.y must be an integer, got {type(y).__name__}: {y}")
43 self.
x = input_list[0]
44 self.
y = input_list[1]
47 return [self.
x, self.
y]
51class int3(ctypes.Structure):
52 _fields_ = [(
'x', ctypes.c_int32), (
'y', ctypes.c_int32), (
'z', ctypes.c_int32)]
55 return f
'int3({self.x}, {self.y}, {self.z})'
58 return f
'int3({self.x}, {self.y}, {self.z})'
61 """Create instance - only pass cls to prevent TypeError on Windows."""
62 return ctypes.Structure.__new__(cls)
64 def __init__(self, x:int=0, y:int=0, z:int=0):
66 if not isinstance(x, int):
67 raise ValueError(f
"int3.x must be an integer, got {type(x).__name__}: {x}")
68 if not isinstance(y, int):
69 raise ValueError(f
"int3.y must be an integer, got {type(y).__name__}: {y}")
70 if not isinstance(z, int):
71 raise ValueError(f
"int3.z must be an integer, got {type(z).__name__}: {z}")
77 def from_list(self, input_list:List[int]):
78 self.
x = input_list[0]
79 self.
y = input_list[1]
80 self.
z = input_list[2]
83 return [self.
x, self.
y, self.
z]
87class int4(ctypes.Structure):
88 _fields_ = [(
'x', ctypes.c_int32), (
'y', ctypes.c_int32), (
'z', ctypes.c_int32), (
'w', ctypes.c_int32)]
91 return f
'int4({self.x}, {self.y}, {self.z}, {self.w})'
94 return f
'int4({self.x}, {self.y}, {self.z}, {self.w})'
96 def __new__(cls, x=None, y=None, z=None, w=None):
97 """Create instance - only pass cls to prevent TypeError on Windows."""
98 return ctypes.Structure.__new__(cls)
100 def __init__(self, x:int=0, y:int=0, z:int=0, w:int=0):
102 if not isinstance(x, int):
103 raise ValueError(f
"int4.x must be an integer, got {type(x).__name__}: {x}")
104 if not isinstance(y, int):
105 raise ValueError(f
"int4.y must be an integer, got {type(y).__name__}: {y}")
106 if not isinstance(z, int):
107 raise ValueError(f
"int4.z must be an integer, got {type(z).__name__}: {z}")
108 if not isinstance(w, int):
109 raise ValueError(f
"int4.w must be an integer, got {type(w).__name__}: {w}")
116 def from_list(self, input_list:List[int]):
117 self.
x = input_list[0]
118 self.
y = input_list[1]
119 self.
z = input_list[2]
120 self.
w = input_list[3]
123 return [self.
x, self.
y, self.
z, self.
w]
127class vec2(ctypes.Structure):
128 _fields_ = [(
'x', ctypes.c_float), (
'y', ctypes.c_float)]
131 return f
'vec2({self.x}, {self.y})'
134 return f
'vec2({self.x}, {self.y})'
137 """Create instance - only pass cls to prevent TypeError on Windows."""
138 return ctypes.Structure.__new__(cls)
143 raise ValueError(f
"vec2.x must be a finite number, got {type(x).__name__}: {x}. "
144 f
"Vector components must be finite (not NaN or infinity).")
146 raise ValueError(f
"vec2.y must be a finite number, got {type(y).__name__}: {y}. "
147 f
"Vector components must be finite (not NaN or infinity).")
153 self.
x = input_list[0]
154 self.
y = input_list[1]
156 def to_list(self) -> List[float]:
157 return [self.
x, self.
y]
160 """Return the magnitude (length) of the vector."""
162 return math.sqrt(self.
x * self.
x + self.
y * self.
y)
165 """Return a normalized copy of this vector (unit length)."""
169 return vec2(self.
x / mag, self.
y / mag)
173 """Check if value is a finite number (not NaN or inf)."""
175 float_value = float(value)
176 return math.isfinite(float_value)
177 except (ValueError, TypeError, OverflowError):
180class vec3(ctypes.Structure):
181 _fields_ = [(
'x', ctypes.c_float), (
'y', ctypes.c_float), (
'z', ctypes.c_float)]
184 return f
'vec3({self.x}, {self.y}, {self.z})'
187 return f
'vec3({self.x}, {self.y}, {self.z})'
189 def __new__(cls, x=None, y=None, z=None):
190 """Create instance - only pass cls to prevent TypeError on Windows."""
191 return ctypes.Structure.__new__(cls)
193 def __init__(self, x:float=0, y:float=0, z:float=0):
196 raise ValueError(f
"vec3.x must be a finite number, got {type(x).__name__}: {x}. "
197 f
"Vector components must be finite (not NaN or infinity).")
199 raise ValueError(f
"vec3.y must be a finite number, got {type(y).__name__}: {y}. "
200 f
"Vector components must be finite (not NaN or infinity).")
202 raise ValueError(f
"vec3.z must be a finite number, got {type(z).__name__}: {z}. "
203 f
"Vector components must be finite (not NaN or infinity).")
209 def from_list(self, input_list:List[float]):
210 self.
x = input_list[0]
211 self.
y = input_list[1]
212 self.
z = input_list[2]
214 def to_list(self) -> List[float]:
215 return [self.
x, self.
y, self.
z]
218 return (self.
x, self.
y, self.
z)
221 """Return the magnitude (length) of the vector."""
223 return math.sqrt(self.
x * self.
x + self.
y * self.
y + self.
z * self.
z)
226 """Return a normalized copy of this vector (unit length)."""
230 return vec3(self.
x / mag, self.
y / mag, self.
z / mag)
234 """Check if value is a finite number (not NaN or inf)."""
236 float_value = float(value)
237 return math.isfinite(float_value)
238 except (ValueError, TypeError, OverflowError):
242class vec4(ctypes.Structure):
243 _fields_ = [(
'x', ctypes.c_float), (
'y', ctypes.c_float), (
'z', ctypes.c_float), (
'w', ctypes.c_float)]
246 return f
'vec4({self.x}, {self.y}, {self.z}, {self.w})'
249 return f
'vec4({self.x}, {self.y}, {self.z}, {self.w})'
251 def __new__(cls, x=None, y=None, z=None, w=None):
252 """Create instance - only pass cls to prevent TypeError on Windows."""
253 return ctypes.Structure.__new__(cls)
255 def __init__(self, x:float=0, y:float=0, z:float=0, w:float=0):
258 raise ValueError(f
"vec4.x must be a finite number, got {type(x).__name__}: {x}. "
259 f
"Vector components must be finite (not NaN or infinity).")
261 raise ValueError(f
"vec4.y must be a finite number, got {type(y).__name__}: {y}. "
262 f
"Vector components must be finite (not NaN or infinity).")
264 raise ValueError(f
"vec4.z must be a finite number, got {type(z).__name__}: {z}. "
265 f
"Vector components must be finite (not NaN or infinity).")
267 raise ValueError(f
"vec4.w must be a finite number, got {type(w).__name__}: {w}. "
268 f
"Vector components must be finite (not NaN or infinity).")
275 def from_list(self, input_list:List[float]):
276 self.
x = input_list[0]
277 self.
y = input_list[1]
278 self.
z = input_list[2]
279 self.
w = input_list[3]
281 def to_list(self) -> List[float]:
282 return [self.
x, self.
y, self.
z, self.
w]
286 """Check if value is a finite number (not NaN or inf)."""
288 float_value = float(value)
289 return math.isfinite(float_value)
290 except (ValueError, TypeError, OverflowError):
296 _fields_ = [(
'r', ctypes.c_float), (
'g', ctypes.c_float), (
'b', ctypes.c_float)]
299 return f
'RGBcolor({self.r}, {self.g}, {self.b})'
302 return f
'RGBcolor({self.r}, {self.g}, {self.b})'
304 def __new__(cls, r=None, g=None, b=None):
305 """Create instance - only pass cls to prevent TypeError on Windows."""
306 return ctypes.Structure.__new__(cls)
308 def __init__(self, r:float=0, g:float=0, b:float=0):
310 self._validate_color_component(r,
'r')
311 self._validate_color_component(g,
'g')
312 self._validate_color_component(b,
'b')
318 def from_list(self, input_list:List[float]):
319 self.
r = input_list[0]
320 self.
g = input_list[1]
321 self.
b = input_list[2]
324 return [self.
r, self.
g, self.
b]
326 def scale(self, factor: float) ->
'RGBcolor':
327 """Return a scaled copy of this color, clamped to [0, 1]."""
329 min(1.0, max(0.0, self.
r * factor)),
330 min(1.0, max(0.0, self.
g * factor)),
331 min(1.0, max(0.0, self.
b * factor))
336 """Check if value is a finite number (not NaN or inf)."""
338 float_value = float(value)
339 return math.isfinite(float_value)
340 except (ValueError, TypeError, OverflowError):
345 """Validate a color component is finite and in range [0,1]."""
346 if not RGBcolor._is_finite_numeric(value):
347 raise ValueError(f
"RGBcolor.{component_name} must be a finite number, "
348 f
"got {type(value).__name__}: {value}. "
349 f
"Color components must be finite values between 0 and 1.")
351 if not (0.0 <= value <= 1.0):
352 raise ValueError(f
"RGBcolor.{component_name}={value} is outside valid range [0,1]. "
353 f
"Color components must be normalized values between 0 and 1.")
359 _fields_ = [(
'r', ctypes.c_float), (
'g', ctypes.c_float), (
'b', ctypes.c_float), (
'a', ctypes.c_float)]
362 return f
'RGBAcolor({self.r}, {self.g}, {self.b}, {self.a})'
365 return f
'RGBAcolor({self.r}, {self.g}, {self.b}, {self.a})'
367 def __new__(cls, r=None, g=None, b=None, a=None):
368 """Create instance - only pass cls to prevent TypeError on Windows."""
369 return ctypes.Structure.__new__(cls)
371 def __init__(self, r:float=0, g:float=0, b:float=0, a:float=0):
383 def from_list(self, input_list:List[float]):
384 self.
r = input_list[0]
385 self.
g = input_list[1]
386 self.
b = input_list[2]
387 self.a = input_list[3]
390 return [self.
r, self.
g, self.
b, self.
a]
392 def scale(self, factor: float) ->
'RGBAcolor':
393 """Return a scaled copy of this color, clamped to [0, 1]. Alpha unchanged."""
395 min(1.0, max(0.0, self.
r * factor)),
396 min(1.0, max(0.0, self.
g * factor)),
397 min(1.0, max(0.0, self.
b * factor)),
403 """Check if value is a finite number (not NaN or inf)."""
405 float_value = float(value)
406 return math.isfinite(float_value)
407 except (ValueError, TypeError, OverflowError):
412 """Validate a color component is finite and in range [0,1]."""
413 if not RGBAcolor._is_finite_numeric(value):
414 raise ValueError(f
"RGBAcolor.{component_name} must be a finite number, "
415 f
"got {type(value).__name__}: {value}. "
416 f
"Color components must be finite values between 0 and 1.")
418 if not (0.0 <= value <= 1.0):
419 raise ValueError(f
"RGBAcolor.{component_name}={value} is outside valid range [0,1]. "
420 f
"Color components must be normalized values between 0 and 1.")
426 (
'radius', ctypes.c_float),
427 (
'elevation', ctypes.c_float),
428 (
'zenith', ctypes.c_float),
429 (
'azimuth', ctypes.c_float)
433 return f
'SphericalCoord({self.radius}, {self.elevation}, {self.zenith}, {self.azimuth})'
436 return f
'SphericalCoord({self.radius}, {self.elevation}, {self.zenith}, {self.azimuth})'
438 def __new__(cls, radius=None, elevation=None, azimuth=None):
439 """Create instance - only pass cls to prevent TypeError on Windows."""
440 return ctypes.Structure.__new__(cls)
442 def __init__(self, radius:float=1, elevation:float=0, azimuth:float=0):
444 Initialize SphericalCoord fields with validation.
445 Do not call super().__init__() for Windows compatibility.
448 radius: Radius (default: 1)
449 elevation: Elevation angle in radians (default: 0)
450 azimuth: Azimuthal angle in radians (default: 0)
452 Note: zenith is automatically computed as (Ï€/2 - elevation) to match C++ behavior
456 raise ValueError(f
"SphericalCoord.radius must be a positive finite number, "
457 f
"got {type(radius).__name__}: {radius}. "
458 f
"Radius must be greater than 0.")
461 raise ValueError(f
"SphericalCoord.elevation must be a finite number, "
462 f
"got {type(elevation).__name__}: {elevation}. "
463 f
"Elevation angle must be finite (not NaN or infinity).")
466 raise ValueError(f
"SphericalCoord.azimuth must be a finite number, "
467 f
"got {type(azimuth).__name__}: {azimuth}. "
468 f
"Azimuth angle must be finite (not NaN or infinity).")
471 self.
radius = float(radius)
477 self.
radius = input_list[0]
479 self.
zenith = input_list[2]
482 def to_list(self) -> List[float]:
487 """Check if value is a finite number (not NaN or inf)."""
489 float_value = float(value)
490 return math.isfinite(float_value)
491 except (ValueError, TypeError, OverflowError):
498 Axis rotation structure for specifying shoot orientation in PlantArchitecture.
500 Represents rotation using pitch, yaw, and roll angles in degrees.
501 Used to define the orientation of shoots, stems, and branches during plant construction.
504 (
'pitch', ctypes.c_float),
505 (
'yaw', ctypes.c_float),
506 (
'roll', ctypes.c_float)
510 return f
'AxisRotation({self.pitch}, {self.yaw}, {self.roll})'
513 return f
'AxisRotation({self.pitch}, {self.yaw}, {self.roll})'
515 def __new__(cls, pitch=None, yaw=None, roll=None):
517 Create AxisRotation instance.
518 Only pass cls to parent __new__ to prevent TypeError on Windows.
520 return ctypes.Structure.__new__(cls)
522 def __init__(self, pitch:float=0, yaw:float=0, roll:float=0):
524 Initialize AxisRotation fields with validation.
525 Do not call super().__init__() for Windows compatibility.
528 pitch: Pitch angle in degrees (rotation about transverse axis)
529 yaw: Yaw angle in degrees (rotation about vertical axis)
530 roll: Roll angle in degrees (rotation about longitudinal axis)
533 ValueError: If any angle value is not finite
537 raise ValueError(f
"AxisRotation.pitch must be a finite number, got {type(pitch).__name__}: {pitch}. "
538 f
"Rotation angles must be finite (not NaN or infinity).")
540 raise ValueError(f
"AxisRotation.yaw must be a finite number, got {type(yaw).__name__}: {yaw}. "
541 f
"Rotation angles must be finite (not NaN or infinity).")
543 raise ValueError(f
"AxisRotation.roll must be a finite number, got {type(roll).__name__}: {roll}. "
544 f
"Rotation angles must be finite (not NaN or infinity).")
546 self.
pitch = float(pitch)
547 self.
yaw = float(yaw)
548 self.
roll = float(roll)
550 def from_list(self, input_list:List[float]):
551 """Initialize from list [pitch, yaw, roll]"""
552 if len(input_list) < 3:
553 raise ValueError(
"AxisRotation.from_list requires a list with at least 3 elements [pitch, yaw, roll]")
554 self.
pitch = input_list[0]
556 self.
roll = input_list[2]
559 """Convert to list [pitch, yaw, roll]"""
564 """Check if value is a finite number (not NaN or inf)."""
566 float_value = float(value)
567 return math.isfinite(float_value)
568 except (ValueError, TypeError, OverflowError):
574 """Make an int2 from two integers"""
577def make_SphericalCoord(elevation_radians: float, azimuth_radians: float) -> SphericalCoord:
579 Make a SphericalCoord by specifying elevation and azimuth (C++ API compatibility).
582 elevation_radians: Elevation angle in radians
583 azimuth_radians: Azimuthal angle in radians
586 SphericalCoord with radius=1, and automatically computed zenith
588 return SphericalCoord(radius=1, elevation=elevation_radians, azimuth=azimuth_radians)
590def make_int3(x: int, y: int, z: int) -> int3:
591 """Make an int3 from three integers"""
595 """Make an int4 from four integers"""
596 return int4(x, y, z, w)
598def make_vec2(x: float, y: float) -> vec2:
599 """Make a vec2 from two floats"""
602def make_vec3(x: float, y: float, z: float) -> vec3:
603 """Make a vec3 from three floats"""
606def make_vec4(x: float, y: float, z: float, w: float) -> vec4:
607 """Make a vec4 from four floats"""
608 return vec4(x, y, z, w)
611 """Make an RGBcolor from three floats"""
614def make_RGBAcolor(r: float, g: float, b: float, a: float) -> RGBAcolor:
615 """Make an RGBAcolor from four floats"""
619 """Make an AxisRotation from three angles in degrees"""
623class Time(ctypes.Structure):
624 """Helios Time structure for representing time values."""
625 _fields_ = [(
'second', ctypes.c_int32), (
'minute', ctypes.c_int32), (
'hour', ctypes.c_int32)]
627 def __repr__(self) -> str:
628 return f
'Time({self.hour:02d}:{self.minute:02d}:{self.second:02d})'
630 def __str__(self) -> str:
631 return f
'{self.hour:02d}:{self.minute:02d}:{self.second:02d}'
633 def __new__(cls, hour=None, minute=None, second=None):
634 """Create instance - only pass cls to prevent TypeError on Windows."""
635 return ctypes.Structure.__new__(cls)
637 def __init__(self, hour: int = 0, minute: int = 0, second: int = 0):
639 Initialize Time fields with validation.
640 Do not call super().__init__() for Windows compatibility.
644 minute: Minute (0-59)
645 second: Second (0-59)
648 if not isinstance(hour, int):
649 raise ValueError(f
"Time.hour must be an integer, got {type(hour).__name__}: {hour}")
650 if not isinstance(minute, int):
651 raise ValueError(f
"Time.minute must be an integer, got {type(minute).__name__}: {minute}")
652 if not isinstance(second, int):
653 raise ValueError(f
"Time.second must be an integer, got {type(second).__name__}: {second}")
655 if hour < 0
or hour > 23:
656 raise ValueError(f
"Time.hour must be between 0 and 23, got: {hour}")
657 if minute < 0
or minute > 59:
658 raise ValueError(f
"Time.minute must be between 0 and 59, got: {minute}")
659 if second < 0
or second > 59:
660 raise ValueError(f
"Time.second must be between 0 and 59, got: {second}")
667 def from_list(self, input_list: List[int]):
668 """Initialize from a list [hour, minute, second]"""
669 if len(input_list) < 3:
670 raise ValueError(
"Time.from_list requires a list with at least 3 elements [hour, minute, second]")
671 self.hour = input_list[0]
673 self.
second = input_list[2]
675 def to_list(self) -> List[int]:
676 """Convert to list [hour, minute, second]"""
679 def __eq__(self, other) -> bool:
680 """Check equality with another Time object"""
681 if not isinstance(other, Time):
683 return (self.
hour == other.hour
and
684 self.
minute == other.minute
and
687 def __ne__(self, other) -> bool:
688 """Check inequality with another Time object"""
689 return not self.
__eq__(other)
692class Date(ctypes.Structure):
693 """Helios Date structure for representing date values."""
694 _fields_ = [(
'day', ctypes.c_int32), (
'month', ctypes.c_int32), (
'year', ctypes.c_int32)]
697 return f
'Date({self.year}-{self.month:02d}-{self.day:02d})'
700 return f
'{self.year}-{self.month:02d}-{self.day:02d}'
702 def __new__(cls, year=None, month=None, day=None):
703 """Create instance - only pass cls to prevent TypeError on Windows."""
704 return ctypes.Structure.__new__(cls)
706 def __init__(self, year: int = 2023, month: int = 1, day: int = 1):
708 Initialize Date fields with validation.
709 Do not call super().__init__() for Windows compatibility.
712 year: Year (1900-3000)
717 if not isinstance(year, int):
718 raise ValueError(f
"Date.year must be an integer, got {type(year).__name__}: {year}")
719 if not isinstance(month, int):
720 raise ValueError(f
"Date.month must be an integer, got {type(month).__name__}: {month}")
721 if not isinstance(day, int):
722 raise ValueError(f
"Date.day must be an integer, got {type(day).__name__}: {day}")
724 if year < 1900
or year > 3000:
725 raise ValueError(f
"Date.year must be between 1900 and 3000, got: {year}")
726 if month < 1
or month > 12:
727 raise ValueError(f
"Date.month must be between 1 and 12, got: {month}")
728 if day < 1
or day > 31:
729 raise ValueError(f
"Date.day must be between 1 and 31, got: {day}")
736 def from_list(self, input_list: List[int]):
737 """Initialize from a list [year, month, day]"""
738 if len(input_list) < 3:
739 raise ValueError(
"Date.from_list requires a list with at least 3 elements [year, month, day]")
740 self.year = input_list[0]
741 self.month = input_list[1]
742 self.day = input_list[2]
745 """Convert to list [year, month, day]"""
749 """Calculate Julian day number for this date."""
751 y = self.
year + 4800 - a
752 m = self.
month + 12 * a - 3
753 return self.
day + (153 * m + 2) // 5 + 365 * y + y // 4 - y // 100 + y // 400 - 32045
756 """Return a new Date object incremented by one day."""
758 days_in_month = calendar.monthrange(self.
year, self.
month)[1]
760 new_day = self.
day + 1
761 new_month = self.
month
764 if new_day > days_in_month:
771 return Date(new_year, new_month, new_day)
774 """Check if this date's year is a leap year."""
775 return (self.
year % 4 == 0
and self.
year % 100 != 0)
or (self.
year % 400 == 0)
777 def __eq__(self, other) -> bool:
778 """Check equality with another Date object"""
779 if not isinstance(other, Date):
781 return (self.
year == other.year
and
782 self.
month == other.month
and
783 self.
day == other.day)
785 def __ne__(self, other) -> bool:
786 """Check inequality with another Date object"""
790def make_Time(hour: int, minute: int, second: int) -> Time:
791 """Make a Time from hour, minute, second"""
792 return Time(hour, minute, second)
794def make_Date(year: int, month: int, day: int) -> Date:
795 """Make a Date from year, month, day"""
796 return Date(year, month, day)
Axis rotation structure for specifying shoot orientation in PlantArchitecture.
bool _is_finite_numeric(value)
Check if value is a finite number (not NaN or inf).
List[float] to_list(self)
Convert to list [pitch, yaw, roll].
from_list(self, List[float] input_list)
Initialize from list [pitch, yaw, roll].
Helios Date structure for representing date values.
bool isLeapYear(self)
Check if this date's year is a leap year.
bool __ne__(self, other)
Check inequality with another Date object.
'Date' incrementDay(self)
Return a new Date object incremented by one day.
bool __eq__(self, other)
Check equality with another Date object.
List[int] to_list(self)
Convert to list [year, month, day].
int JulianDay(self)
Calculate Julian day number for this date.
Helios primitive type enumeration.
List[float] to_list(self)
_validate_color_component(value, component_name)
Validate a color component is finite and in range [0,1].
bool _is_finite_numeric(value)
Check if value is a finite number (not NaN or inf).
'RGBAcolor' scale(self, float factor)
Return a scaled copy of this color, clamped to [0, 1].
__init__(self, float r=0, float g=0, float b=0, float a=0)
__new__(cls, r=None, g=None, b=None, a=None)
Create only pass cls to prevent TypeError on Windows.
'RGBcolor' scale(self, float factor)
Return a scaled copy of this color, clamped to [0, 1].
__new__(cls, r=None, g=None, b=None)
Create only pass cls to prevent TypeError on Windows.
__init__(self, float r=0, float g=0, float b=0)
from_list(self, List[float] input_list)
List[float] to_list(self)
_validate_color_component(value, component_name)
Validate a color component is finite and in range [0,1].
bool _is_finite_numeric(value)
Check if value is a finite number (not NaN or inf).
List[float] to_list(self)
from_list(self, List[float] input_list)
bool _is_finite_numeric(value)
Check if value is a finite number (not NaN or inf).
__init__(self, float radius=1, float elevation=0, float azimuth=0)
Initialize SphericalCoord fields with validation.
__new__(cls, radius=None, elevation=None, azimuth=None)
Create only pass cls to prevent TypeError on Windows.
Helios Time structure for representing time values.
__new__(cls, hour=None, minute=None, second=None)
Create only pass cls to prevent TypeError on Windows.
List[int] to_list(self)
Convert to list [hour, minute, second].
from_list(self, List[int] input_list)
Initialize from a list [hour, minute, second].
__init__(self, int hour=0, int minute=0, int second=0)
Initialize Time fields with validation.
bool __eq__(self, other)
Check equality with another Time object.
bool __ne__(self, other)
Check inequality with another Time object.
from_list(self, List[int] input_list)
__init__(self, int x=0, int y=0)
__new__(cls, x=None, y=None)
Create only pass cls to prevent TypeError on Windows.
__init__(self, int x=0, int y=0, int z=0)
from_list(self, List[int] input_list)
__new__(cls, x=None, y=None, z=None)
Create only pass cls to prevent TypeError on Windows.
from_list(self, List[int] input_list)
__init__(self, int x=0, int y=0, int z=0, int w=0)
__new__(cls, x=None, y=None, z=None, w=None)
Create only pass cls to prevent TypeError on Windows.
from_list(self, List[float] input_list)
'vec2' normalize(self)
Return a normalized copy of this vector (unit length).
bool _is_finite_numeric(value)
Check if value is a finite number (not NaN or inf).
float magnitude(self)
Return the magnitude (length) of the vector.
__new__(cls, x=None, y=None)
Create only pass cls to prevent TypeError on Windows.
List[float] to_list(self)
__init__(self, float x=0, float y=0)
List[float] to_list(self)
__init__(self, float x=0, float y=0, float z=0)
from_list(self, List[float] input_list)
'vec3' normalize(self)
Return a normalized copy of this vector (unit length).
__new__(cls, x=None, y=None, z=None)
Create only pass cls to prevent TypeError on Windows.
float magnitude(self)
Return the magnitude (length) of the vector.
bool _is_finite_numeric(value)
Check if value is a finite number (not NaN or inf).
List[float] to_list(self)
bool _is_finite_numeric(value)
Check if value is a finite number (not NaN or inf).
__init__(self, float x=0, float y=0, float z=0, float w=0)
__new__(cls, x=None, y=None, z=None, w=None)
Create only pass cls to prevent TypeError on Windows.
from_list(self, List[float] input_list)
RGBAcolor make_RGBAcolor(float r, float g, float b, float a)
Make an RGBAcolor from four floats.
AxisRotation make_AxisRotation(float pitch, float yaw, float roll)
Make an AxisRotation from three angles in degrees.
int3 make_int3(int x, int y, int z)
Make an int3 from three integers.
Time make_Time(int hour, int minute, int second)
Make a Time from hour, minute, second.
RGBcolor make_RGBcolor(float r, float g, float b)
Make an RGBcolor from three floats.
Date make_Date(int year, int month, int day)
Make a Date from year, month, day.
int4 make_int4(int x, int y, int z, int w)
Make an int4 from four integers.
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth (C++ API compatibility).
vec2 make_vec2(float x, float y)
Make a vec2 from two floats.
vec4 make_vec4(float x, float y, float z, float w)
Make a vec4 from four floats.
int2 make_int2(int x, int y)
Make an int2 from two integers.
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.