diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f7081a2..9734d021 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,8 +11,8 @@ jobs: strategy: fail-fast: false matrix: - numpy-version: ["oldest-supported-numpy", "numpy"] - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] + numpy-version: ["numpy"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - name: Checkout code uses: actions/checkout@v4 @@ -21,8 +21,8 @@ jobs: with: python-version: ${{ matrix.python-version }} - name: Install Python dependencies - run: python -m pip install --prefer-binary setuptools "cython>=0.28,<3.0" "matplotlib>=3,<4" ${{ matrix.numpy-version }} + run: python -m pip install --prefer-binary meson-python meson ninja setuptools setuptools-scm "cython>=3.1" "matplotlib>=3,<4" ${{ matrix.numpy-version }} - name: Build and install Raysect - run: dev/build.sh + run: dev/install_editable.sh - name: Run tests run: dev/test.sh diff --git a/.gitignore b/.gitignore index 2e0ea683..5438adae 100644 --- a/.gitignore +++ b/.gitignore @@ -6,10 +6,12 @@ __pycache__/ # C extensions *.so *.c + # Distribution / packaging +/build/ .Python env/ -build/ +venv/ develop-eggs/ dist/ downloads/ @@ -58,4 +60,5 @@ docs/build/ # PyBuilder target/ - +# setuptools-scm +raysect/_version.py diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 1c23752b..6ceb55db 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,6 +1,32 @@ Raysect Changelog ================= +Release 0.9.0 (TBD) +------------------- + +Build changes: +* The legacy setuptools build system has been replaced with meson-python. + - The dev/build.sh and dev/clean.sh scripts have been updated to work with the new build system. + - A meson.build generator script is provided to automate the discovery of pyx, pxd,py and data files. Please see dev/generate_meson_files.py. + - When installed in editable mode, any modified pyx files will automatically trigger a rebuild when python attempts to import from the package. Please be aware that (as with the previous build system) changes to pxd files will require a clean rebuild of the project. + - A dev/install_editable.sh script is provided to simplify the installation of the package in editable mode with verbose build output enabled. + - Meson-python performs the build out of the project folder, so the project source folders will no longer be polluted with build artefacts. + - Cython build annotations are now always enabled, the annotation files can be found in the build folder under the build artefacts folder associated with each so file (*.so.p folder). +* The codebase has been migrated to Cython 3. + - This migration was made possible due to the contributions of Koyo Munechika (@munechika-koyo). + +Python support: +* Raysect now requires Python v3.9 and above. + - From version v0.9.0 Raysect is dropping support for Python versions older than v3.9. + - Users of older versions of Python should remain using Raysect v0.8.1 and plan for a migration to v0.9.0+. + +API changes: +* Corrected spelling of all classes, methods and functions where "targeted" was incorrectly spelt "targetted". + +New: +* Added a torus primitive (contribute by Koyo Munechika). + + Release 0.8.1 (12 Feb 2023) --------------------------- diff --git a/LICENSE.txt b/LICENSE.txt index b29173f4..efc7d020 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2014-2021, Dr Alex Meakins, Raysect Project +Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 858ec3f7..00000000 --- a/MANIFEST.in +++ /dev/null @@ -1,6 +0,0 @@ -include README.md CHANGELOG.txt LICENSE.txt CONTRIBUTING.txt AUTHORS.txt MANIFEST.in setup.py .gitignore -include raysect/VERSION -global-exclude *.c -recursive-include raysect *.py *.pyx *.pxd *.csv *.json -recursive-include demos *.py *.pyx *.pxd *.csv *.obj *.rsm -recursive-include docs * diff --git a/README.md b/README.md index 4afa7ea2..cecaaba2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1341346.svg)](https://doi.org/10.5281/zenodo.1341346) -[![Build Status](https://travis-ci.com/raysect/source.svg?branch=master)](https://travis-ci.com/raysect/source) diff --git a/demos/materials/modifiers/transform.py b/demos/materials/modifiers/transform.py index 924b3288..e7151d02 100644 --- a/demos/materials/modifiers/transform.py +++ b/demos/materials/modifiers/transform.py @@ -18,7 +18,7 @@ def emission_function(self, point, direction, spectrum, world, ray, primitive, t wvl_range = spectrum.min_wavelength - spectrum.max_wavelength shift = 2 * (spectrum.wavelengths - wvl_centre) / wvl_range radius = sqrt(point.x**2 + point.y**2) - spectrum.samples += cos((shift + 5) * radius)**4 + spectrum.samples[:] += cos((shift + 5) * radius)**4 return spectrum diff --git a/demos/materials/volume.py b/demos/materials/volume.py index 8ab7c002..ddcc9134 100644 --- a/demos/materials/volume.py +++ b/demos/materials/volume.py @@ -20,7 +20,7 @@ def emission_function(self, point, direction, spectrum, world, ray, primitive, t wvl_range = spectrum.min_wavelength - spectrum.max_wavelength shift = 2 * (spectrum.wavelengths - wvl_centre) / wvl_range radius = sqrt(point.x**2 + point.y**2) - spectrum.samples += cos((shift + 5) * radius)**4 + spectrum.samples[:] += cos((shift + 5) * radius)**4 return spectrum diff --git a/demos/maths/plot_targetted_sampler.py b/demos/maths/plot_targeted_sampler.py similarity index 86% rename from demos/maths/plot_targetted_sampler.py rename to demos/maths/plot_targeted_sampler.py index 0978a647..d46f2a7b 100644 --- a/demos/maths/plot_targetted_sampler.py +++ b/demos/maths/plot_targeted_sampler.py @@ -2,7 +2,7 @@ import matplotlib.pyplot as plt from math import atan2, sqrt, degrees -from raysect.core.math import Point3D, TargettedHemisphereSampler, TargettedSphereSampler +from raysect.core.math import Point3D, TargetedHemisphereSampler, TargetedSphereSampler def display_samples(samples, title): @@ -34,8 +34,8 @@ def display_samples(samples, title): observation_point = Point3D(0, 0, 0) # generate samplers -hemisphere = TargettedHemisphereSampler(targets) -sphere = TargettedSphereSampler(targets) +hemisphere = TargetedHemisphereSampler(targets) +sphere = TargetedSphereSampler(targets) # sample for origin point and point at (0, 0, -10) h_samples = hemisphere(observation_point, samples=samples) diff --git a/demos/observers/cornell_box_cooke_triplet.py b/demos/observers/cornell_box_cooke_triplet.py index 2f7ee055..653632f2 100644 --- a/demos/observers/cornell_box_cooke_triplet.py +++ b/demos/observers/cornell_box_cooke_triplet.py @@ -4,7 +4,7 @@ from raysect.optical import World, Node, translate, rotate, Point3D from raysect.optical.material import Lambert, UniformSurfaceEmitter, AbsorbingSurface, Checkerboard from raysect.optical.library import * -from raysect.optical.observer import TargettedCCDArray +from raysect.optical.observer import TargetedCCDArray from raysect.optical.observer import RGBPipeline2D, BayerPipeline2D, PowerPipeline2D from raysect.optical.observer import RGBAdaptiveSampler2D from raysect.core.math import mm @@ -184,9 +184,9 @@ rgb = RGBPipeline2D(display_unsaturated_fraction=0.96, name="sRGB") sampler = RGBAdaptiveSampler2D(rgb, ratio=10, fraction=0.2, min_samples=1000, cutoff=0.01) -# CCD targetting all rays at last lens element for speed -ccd = TargettedCCDArray( - targetted_path_prob=1.0, targets=[l3], +# CCD targeting all rays at last lens element for speed +ccd = TargetedCCDArray( + targeted_path_prob=1.0, targets=[l3], width=mm(35), pixels=(512, 512), parent=image_plane, transform=translate(0, 0, 0)*rotate(0, 0, 180), pipelines=[rgb] diff --git a/demos/observers/cornell_box_real_pinhole.py b/demos/observers/cornell_box_real_pinhole.py index 64e43e38..d456cc13 100644 --- a/demos/observers/cornell_box_real_pinhole.py +++ b/demos/observers/cornell_box_real_pinhole.py @@ -5,7 +5,7 @@ from raysect.optical import World, Node, translate, rotate, Point3D from raysect.optical.material import Lambert, UniformSurfaceEmitter, NullMaterial from raysect.optical.library import * -from raysect.optical.observer import RGBPipeline2D, BayerPipeline2D, PowerPipeline2D, TargettedCCDArray +from raysect.optical.observer import RGBPipeline2D, BayerPipeline2D, PowerPipeline2D, TargetedCCDArray from raysect.optical.observer import RGBAdaptiveSampler2D @@ -144,7 +144,7 @@ camera = Node(parent=world, transform=translate(0, 0, -3.3)) pinhole = Sphere(0.0005, camera, transform=translate(0, 0, 0), material=NullMaterial()) -film = TargettedCCDArray(targetted_path_prob=1.0, targets=[pinhole], width=0.1, pixels=(512, 512), parent=camera, +film = TargetedCCDArray(targeted_path_prob=1.0, targets=[pinhole], width=0.1, pixels=(512, 512), parent=camera, transform=translate(0, 0, -0.1207), pipelines=pipelines) film.frame_sampler = sampler film.pixel_samples = 250 diff --git a/demos/observers/metal_with_lens.py b/demos/observers/metal_with_lens.py index c9bd9163..a5bcc6ce 100644 --- a/demos/observers/metal_with_lens.py +++ b/demos/observers/metal_with_lens.py @@ -7,7 +7,7 @@ from raysect.optical.library.metal import Gold, Silver, Copper, Titanium, Aluminium, Beryllium from raysect.optical.material import Lambert, UniformSurfaceEmitter, AbsorbingSurface, NullMaterial from raysect.optical.library import schott -from raysect.optical.observer import RGBPipeline2D, BayerPipeline2D, TargettedCCDArray, CCDArray, RGBAdaptiveSampler2D +from raysect.optical.observer import RGBPipeline2D, BayerPipeline2D, TargetedCCDArray, CCDArray, RGBAdaptiveSampler2D from raysect.optical.colour import ciexyz_x, ciexyz_y, ciexyz_z @@ -49,7 +49,7 @@ pipelines = [rgb, bayer] # ccd = CCDArray(parent=camera, pipelines=pipelines) -ccd = TargettedCCDArray(targets=[aperture], parent=camera, pipelines=pipelines) +ccd = TargetedCCDArray(targets=[aperture], parent=camera, pipelines=pipelines) ccd.frame_sampler = sampler ccd.pixels = (180*2, 120*2) # (360, 240) ccd.pixel_samples = 250 @@ -65,3 +65,6 @@ # ccd.pipelines[0].save("demo_metal_lens_{}.png".format(p)) print() p += 1 + +ioff() +show() diff --git a/demos/observers/targetted_pixel.py b/demos/observers/targeted_pixel.py similarity index 76% rename from demos/observers/targetted_pixel.py rename to demos/observers/targeted_pixel.py index ff272219..8ca58ed1 100644 --- a/demos/observers/targetted_pixel.py +++ b/demos/observers/targeted_pixel.py @@ -3,7 +3,7 @@ from raysect.primitive import Box from raysect.optical import World, translate, Point3D, Node -from raysect.optical.observer import Pixel, TargettedPixel, PowerPipeline0D +from raysect.optical.observer import Pixel, TargetedPixel, PowerPipeline0D from raysect.optical.material import UnitySurfaceEmitter @@ -28,16 +28,16 @@ basic_pipeline = PowerPipeline0D(name="Basic Pixel Observer") basic_pixel = Pixel(parent=world, pixel_samples=SAMPLES, pipelines=[basic_pipeline]) -# setup targetted pixel -targetted_pipeline = PowerPipeline0D(name="Targeted Pixel Observer") -targetted_pixel = TargettedPixel(parent=world, targets=targets, pixel_samples=SAMPLES, pipelines=[targetted_pipeline]) -targetted_pixel.targetted_path_prob = 1 +# setup targeted pixel +targeted_pipeline = PowerPipeline0D(name="Targeted Pixel Observer") +targeted_pixel = TargetedPixel(parent=world, targets=targets, pixel_samples=SAMPLES, pipelines=[targeted_pipeline]) +targeted_pixel.targeted_path_prob = 1 # render ion() basic_pixel.observe() print() -targetted_pixel.observe() +targeted_pixel.observe() ioff() show() diff --git a/demos/optics/etendue_of_pinhole.py b/demos/optics/etendue_of_pinhole.py index 5f15dabc..e1daac54 100644 --- a/demos/optics/etendue_of_pinhole.py +++ b/demos/optics/etendue_of_pinhole.py @@ -3,7 +3,7 @@ import matplotlib.pyplot as plt from raysect.core import Point3D, Vector3D, rotate_basis, translate, Ray as CoreRay -from raysect.core.math.sampler import DiskSampler3D, RectangleSampler3D, TargettedHemisphereSampler +from raysect.core.math.sampler import DiskSampler3D, RectangleSampler3D, TargetedHemisphereSampler from raysect.optical import World from raysect.primitive import Box, Cylinder, Subtract from raysect.optical.material import AbsorbingSurface, NullMaterial @@ -35,8 +35,8 @@ def raytraced_etendue(distance, detector_radius=0.001, ray_count=100000, batches sphere = target.bounding_sphere() spheres = [(sphere.centre.transform(detector_transform), sphere.radius, 1.0)] - # instance targetted pixel sampler - targetted_sampler = TargettedHemisphereSampler(spheres) + # instance targeted pixel sampler + targeted_sampler = TargetedHemisphereSampler(spheres) point_sampler = DiskSampler3D(detector_radius) @@ -53,8 +53,8 @@ def raytraced_etendue(distance, detector_radius=0.001, ray_count=100000, batches passed = 0.0 for origin in origins: - # obtain targetted vector sample - direction, pdf = targetted_sampler(origin, pdf=True) + # obtain targeted vector sample + direction, pdf = targeted_sampler(origin, pdf=True) path_weight = R_2_PI * direction.z/pdf origin = origin.transform(detector_transform) @@ -110,12 +110,10 @@ def raytraced_etendue(distance, detector_radius=0.001, ray_count=100000, batches raytraced_values = np.array(raytraced_values) raytraced_errors = np.array(raytraced_errors) -plt.ion() - plt.figure() ax = plt.gca() -ax.set_xscale("log", nonposx='clip') -ax.set_yscale("log", nonposy='clip') +ax.set_xscale("log", nonpositive='clip') +ax.set_yscale("log", nonpositive='clip') plt.axhline(y=detector_etendue, linestyle='--', color='k', label='detector etendue') plt.plot(distance_samples, analytic_values, label='analytic etendue') plt.errorbar(distance_samples, raytraced_values, raytraced_errors, label='ray-traced etendue') @@ -126,12 +124,11 @@ def raytraced_etendue(distance, detector_radius=0.001, ray_count=100000, batches # plt.figure() # ax = plt.gca() -# ax.set_xscale("log", nonposx='clip') +# ax.set_xscale("log", nonpositive='clip') # plt.errorbar(distance_samples, np.abs(raytraced_values-analytic_values)/raytraced_values, raytraced_errors/raytraced_values) # plt.xlim(0.001, 0.1) # plt.ylim(0, 0.5) # plt.xlabel('Distance between slit and detector (m)') # plt.ylabel('Fractional error') -# plt.show() - +plt.show() diff --git a/demos/optics/logging_trajectories.py b/demos/optics/logging_trajectories.py index 97817a59..c5bb9c39 100644 --- a/demos/optics/logging_trajectories.py +++ b/demos/optics/logging_trajectories.py @@ -28,8 +28,7 @@ # for each sample direction trace a logging ray and plot the ray trajectory plt.ion() -fig = plt.figure() -ax = fig.gca(projection='3d') +ax = plt.axes(projection='3d') for u in np.linspace(-0.006, 0.006, 5): for v in np.linspace(-0.012, 0.012, 11): @@ -39,7 +38,8 @@ log_ray.trace(world) p = [(start.x, start.y, start.z)] - for point in log_ray.log: + for intersection in log_ray.log: + point = intersection.hit_point p.append((point.x, point.y, point.z)) p = np.array(p) diff --git a/demos/primitives/raysect_primitives.py b/demos/primitives/raysect_primitives.py new file mode 100644 index 00000000..9e6825fd --- /dev/null +++ b/demos/primitives/raysect_primitives.py @@ -0,0 +1,126 @@ +# External imports +from time import strftime + +from matplotlib import pyplot as plt + +# Raysect imports +from raysect.optical import Point3D, World, d65_white, rotate, translate +from raysect.optical.library import schott +from raysect.optical.material import Checkerboard, Lambert +from raysect.optical.observer import PinholeCamera, RGBAdaptiveSampler2D, RGBPipeline2D +from raysect.primitive import Box, Cone, Cylinder, Parabola, Sphere, Torus + +# 1. Create Primitives +# -------------------- + +# Box defining the ground plane +ground = Box( + lower=Point3D(-50, -0.01, -50), upper=Point3D(50, 0.0, 50), material=Lambert() +) + +# checker board wall that acts as emitter +emitter = Box( + lower=Point3D(-100, -100, 10), + upper=Point3D(100, 100, 10.1), + material=Checkerboard(4, d65_white, d65_white, 0.1, 2.0), +) + +# Primitive showcasing all geometric features +# Note that the primitives must be displaced slightly above the ground plane to prevent numerically issues that could +# cause a light leak at the intersection between the objects and the ground. +cylinder = Cylinder( + radius=1.5, + height=3.0, + transform=translate(1.5 * 3 + 1.0, 0.0001, 0) * rotate(0, 90, 0), + material=schott("N-BK7"), +) +cone = Cone( + radius=1.5, + height=3.0, + transform=translate(1.5 + 0.2, 0.0001, 0) * rotate(0, 90, 0), + material=schott("N-BK7"), +) +sphere = Sphere( + radius=1.5, + transform=translate(-1.5 - 0.2, 1.5 + 0.0001, 0), + material=schott("N-BK7"), +) +box = Box( + lower=Point3D(-1.5, 0.0, -1.5), + upper=Point3D(1.5, 3.0, 1.5), + transform=translate(-1.5 * 3 - 1.0, 0.0001, 0), + material=schott("N-BK7"), +) +parabola = Parabola( + radius=2.0, + height=1.0, + transform=translate(2.5, 1.0 + 0.0001, -5.0) * rotate(0, -90, 0), + material=schott("N-BK7"), +) +torus = Torus( + major_radius=1.0, + minor_radius=0.5, + transform=translate(-2.5, 0.5 + 0.0001, -5.0) * rotate(0, 90, 0), + material=schott("N-BK7"), +) + + +# 2. Add Observer +# --------------- + +# Process the ray-traced spectra with the RGB pipeline. +rgb = RGBPipeline2D(display_unsaturated_fraction=0.96) +sampler = RGBAdaptiveSampler2D( + rgb, ratio=10, fraction=0.2, min_samples=2000, cutoff=0.01 +) + +# camera +camera = PinholeCamera( + (512, 512), pipelines=[rgb], transform=translate(-7, 12, -15) * rotate(-25, -40, 0) +) + +# camera - pixel sampling settings +camera.fov = 45 +camera.pixel_samples = 250 + +# camera - ray sampling settings +camera.spectral_rays = 15 +camera.spectral_bins = 15 +camera.ray_max_depth = 100 +camera.ray_extinction_prob = 0.1 +camera.min_wavelength = 375.0 +camera.max_wavelength = 740.0 + + +# 3. Build Scenegraph +# ------------------- + +world = World() + +ground.parent = world +emitter.parent = world +camera.parent = world +cylinder.parent = world +cone.parent = world +sphere.parent = world +box.parent = world +parabola.parent = world +torus.parent = world + +# 4. Observe() +# ------------ +name = "raysect_primitives" +timestamp = strftime("%Y-%m-%d_%H-%M-%S") +render_pass = 1 +plt.ion() +while not camera.render_complete: + print(f"Rendering pass {render_pass}...") + camera.observe() + rgb.save(f"{name}_{timestamp}_pass_{render_pass}.png") + render_pass += 1 + print() + +# display final result +plt.ioff() +rgb.display() +plt.show() diff --git a/demos/primitives/simple_torus.py b/demos/primitives/simple_torus.py new file mode 100644 index 00000000..91c0d66e --- /dev/null +++ b/demos/primitives/simple_torus.py @@ -0,0 +1,64 @@ +from matplotlib import pyplot as plt + +from raysect.optical import ConstantSF, Point3D, World, d65_white, rotate, translate +from raysect.optical.library.metal import Copper +from raysect.optical.material import Lambert, UniformSurfaceEmitter +from raysect.optical.observer import PinholeCamera, RGBAdaptiveSampler2D, RGBPipeline2D +from raysect.primitive import Box, Cylinder, Torus + +world = World() + +# Torus +torus = Torus( + 1.0, + 0.5, + world, + transform=translate(0, 0.0, 0.6), + material=Copper(), +) + +# floor +Box( + Point3D(-100, -100, -10), + Point3D(100, 100, 0), + parent=world, + material=Lambert(ConstantSF(1.0)), +) + +# emitter +Cylinder( + 3.0, + 100.0, + parent=world, + transform=translate(0, 0, 8) * rotate(90, 0, 0) * translate(0, 0, -50), + material=UniformSurfaceEmitter(d65_white, 1.0), +) + +# camera +rgb = RGBPipeline2D(display_unsaturated_fraction=0.995) +sampler = RGBAdaptiveSampler2D(rgb, min_samples=500, fraction=0.1, cutoff=0.01) +camera = PinholeCamera( + (512, 512), + parent=world, + transform=rotate(0, 45, 0) * translate(0, 0, 5) * rotate(0, -180, 0), + pipelines=[rgb], + frame_sampler=sampler, +) +camera.spectral_bins = 21 +camera.spectral_rays = 1 +camera.pixel_samples = 250 +camera.ray_max_depth = 10000 +camera.ray_extinction_min_depth = 3 +camera.ray_extinction_prob = 0.01 + + +# start ray tracing +plt.ion() +for p in range(0, 1000): + print(f"Rendering pass {p}...") + camera.observe() + print() + +plt.ioff() +rgb.display() +plt.show() diff --git a/dev/build.sh b/dev/build.sh index 732ccd5f..c5bff15a 100755 --- a/dev/build.sh +++ b/dev/build.sh @@ -1,6 +1,7 @@ #!/bin/bash +set -e # exit if an error occurs -CORES=`nproc --all` +BUILD_PATH="build/`dev/build/abi.py`" -echo "Rebuilding Raysect extension modules (in place)..." -python setup.py build_ext -j$CORES --inplace $1 $2 $3 $4 $5 +echo Rebuilding $BUILD_PATH... +meson compile -C $BUILD_PATH diff --git a/dev/build/abi.py b/dev/build/abi.py new file mode 100755 index 00000000..ba72d14a --- /dev/null +++ b/dev/build/abi.py @@ -0,0 +1,50 @@ +#!/bin/env python + +import sys +import sysconfig +from typing import Union + +""" +Derived from the meson-python codebase. Original license terms: + +Copyright © 2022 the meson-python contributors +Copyright © 2021 Quansight Labs and Filipe Laíns + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + + +def get_cpython_abi() -> str: + version = sys.version_info + debug = pymalloc = '' + if version < (3, 8) and _get_config_var('WITH_PYMALLOC', True): + pymalloc = 'm' + return f'cp{version[0]}{version[1]}{debug}{pymalloc}' + + +def _get_config_var(name: str, default: Union[str, int, None] = None) -> Union[str, int, None]: + value: Union[str, int, None] = sysconfig.get_config_var(name) + if value is None: + return default + return value + + +if __name__ == '__main__': + print(get_cpython_abi()) diff --git a/dev/build/add_version_file_to_dist.sh b/dev/build/add_version_file_to_dist.sh new file mode 100755 index 00000000..dd95ae3b --- /dev/null +++ b/dev/build/add_version_file_to_dist.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -e # exit if an error occurs + +if [[ -z "$MESON_SOURCE_ROOT" ]]; then + echo "ERROR: Must be run inside a meson build environment where the variable MESON_SOURCE_ROOT is set." 1>&2 + exit 1 +fi + +if [[ -z "$MESON_DIST_ROOT" ]]; then + echo "ERROR: Must be run inside a meson build environment where the variable MESON_DIST_ROOT is set." 1>&2 + exit 1 +fi + +VERSION_PATH="raysect/_version.py" +SRC_PATH="$MESON_SOURCE_ROOT/$VERSION_PATH" +DIST_PATH="$MESON_DIST_ROOT/$VERSION_PATH" + +echo "Copying $VERSION_PATH to distribution path $DIST_PATH" +cp $SRC_PATH $DIST_PATH diff --git a/dev/build/update_version.sh b/dev/build/update_version.sh new file mode 100755 index 00000000..f167ea3a --- /dev/null +++ b/dev/build/update_version.sh @@ -0,0 +1,2 @@ +#!/bin/bash +python -m setuptools_scm --force-write-version-files diff --git a/dev/build_docs.sh b/dev/build_docs.sh index a104fba8..115dd101 100755 --- a/dev/build_docs.sh +++ b/dev/build_docs.sh @@ -1,13 +1,10 @@ #!/bin/bash echo Building code... - dev/build.sh echo Building docs... - export PYTHONPATH=../:$PYTHONPATH cd docs - make html diff --git a/dev/clean.sh b/dev/clean.sh index 31ba744a..10e86408 100755 --- a/dev/clean.sh +++ b/dev/clean.sh @@ -1,8 +1,8 @@ #!/bin/bash +set -e # exit if an error occurs -echo Removing all .c, .so and .html files... +BUILD_PATH="build/`dev/build/abi.py`" + +echo Cleaning $BUILD_PATH... +meson compile -C $BUILD_PATH --clean -find raysect -type f -name '*.c' -exec rm {} + -find raysect -type f -name '*.so' -exec rm {} + -find raysect -type f -name '*.html' -exec rm {} + -rm build -rf diff --git a/dev/generate_meson_files.py b/dev/generate_meson_files.py new file mode 100755 index 00000000..94936664 --- /dev/null +++ b/dev/generate_meson_files.py @@ -0,0 +1,250 @@ +#!/bin/env python + +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Raysect Project nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +from pathlib import Path + +PACKAGES = ['raysect'] + +EXCLUDE_DIR_FILE = '.meson-exclude' +CUSTOM_MESON_BUILD = '.meson-custom' +EXCLUDED_DIRS = ['__pycache__'] + + +def generate_meson_files(packages): + """ + Generates the meson.build files for the project from a set of template files. + + A root build.meson will be placed in the project root and meson.build files will be generated for the specified + package folders. This script must be executed from the root folder of the project. + + If substantive changes are needed to the meson.build files throughout the project, it will be easier to modify the + templates and trigger the regeneration process. + + This script will remove any existing meson.build files, so be sure any changes are captured before re-running this + script. There are two template files: + + * root-meson.build + * subdir-meson.build + + The root-meson.build file is used to generate the root meson.build for the project. The subdir-meson.build is used + to generate the meson.build files in the project sub-directory. The templates are read and handled as a python + f-strings. See the script implementation for the variables available to the template. The meson.build files will + consist of the template followed by a set of subdir() entries for each descendant of the current sub-directory + (if not excluded). + + A sub-directory may be excluded from the generation process by placing a file in the subfolder called + ".meson-exclude". If the exclusion file is found, the sub-directory and its descendants will be ignored during + the generation process. + + Occasionally a meson.build file may need to be customised in the source tree. Placing a file called ".meson-custom" + in the same directory as the meson.build file will protect the customised file from deletion or replacement by this + script. + + :param packages: A list of package names. + """ + + root_path = Path('.') + package_paths = [Path(package) for package in packages] + + # Walk the project folder and specified packages to remove all (non-custom) meson.build files. + # Any stale meson.build files found in excluded directories are also removed. + _remove_meson_files(root_path, subdirs=package_paths) + + # Add root meson.build file. + _install_root_meson_file(root_path, subdirs=package_paths) + + # Walk the specified packages and add the sub-directory meson.build files. + for path in package_paths: + _install_subdir_meson_files(path) + + +def _remove_meson_files(path, subdirs=None): + """ + Removes any meson.build files found under the directory tree referenced by path. + + By default, this function recurses through the entire directory tree under the supplied path. If sub-dirs is + provided, then only the specified sub-directories will be explored. + """ + + # validate + if not path.is_dir(): + raise ValueError('The supplied path is not a directory.') + + if subdirs and any([not subdir.is_dir() for subdir in subdirs]): + raise ValueError('The list of sub-directories must only contain paths to valid directories.') + + # remove meson.build in this directory if it is not flagged as customised + if not _custom_meson_file(path): + meson_file = path / 'meson.build' + meson_file.unlink(missing_ok=True) + + # generate a list of subdirectories if none supplied + if not subdirs: + subdirs = [child for child in path.iterdir() if child.is_dir()] + + # recurse into sub-directories + for subdir in subdirs: + _remove_meson_files(subdir) + + +def _install_root_meson_file(path, subdirs): + + # validate + if not path.is_dir(): + raise ValueError('The supplied path is not a directory.') + + if any([not subdir.is_dir() for subdir in subdirs]): + raise ValueError('The list of sub-directories must only contain paths to valid directories.') + + # guarantee ordering + subdirs.sort() + + # write meson file + _write_meson_file(path, _generate_root_meson_file(subdirs)) + + +def _install_subdir_meson_files(path): + + # validate + if not path.is_dir(): + raise ValueError('The supplied path is not a directory.') + + # generate a list of subdirectories, filtering excluded + subdirs = [child for child in path.iterdir() if child.is_dir() and not _excluded_dir(child)] + + # guarantee ordering + subdirs.sort() + + # write meson file + _write_meson_file(path, _generate_subdir_meson_file(path, subdirs)) + + # recurse into sub-directories + for subdir in subdirs: + _install_subdir_meson_files(subdir) + + +def _write_meson_file(path, contents): + if not _custom_meson_file(path): + meson_file = path / 'meson.build' + meson_file.write_text(contents) + + +def _custom_meson_file(path): + return (path / CUSTOM_MESON_BUILD).exists() + + +def _excluded_dir(path): + foo = (path / EXCLUDE_DIR_FILE).exists() or path.name in EXCLUDED_DIRS + return foo + + +def _generate_root_meson_file(subdirs): + + # read template + template_path = Path(__file__).parent / 'root-meson.build' + template = template_path.read_text() + + # start contents with a warning + contents = ( + "# WARNING: This file is automatically generated by dev/generate_meson_files.py.\n" + "# The template file used to generate this file is dev/root-meson.build.\n\n" + ) + + # add template + contents += template + + # add subdir entries + contents += '\n' + for subdir in subdirs: + contents += f'subdir(\'{subdir.name}\')\n' + + return contents + + +def _generate_subdir_meson_file(path, subdirs): + + # read template + template_path = Path(__file__).parent / 'subdir-meson.build' + template = template_path.read_text() + + # build file lists + pyx = [] + pxd = [] + py = [] + data = [] + for child in path.iterdir(): + + if child.is_dir(): + continue + + elif child.suffix == '.pyx': + pyx.append(child.name) + + elif child.suffix == '.pxd': + pxd.append(child.name) + + elif child.suffix == '.py': + py.append(child.name) + + else: + data.append(child.name) + + # guarantee ordering + pyx.sort() + pxd.sort() + py.sort() + data.sort() + + # start contents with a warning + contents = ( + "# WARNING: This file is automatically generated by dev/generate_meson_files.py.\n" + "# The template file used to generate this file is dev/subdir-meson.build.\n\n" + ) + + # add template, filling in the variables + contents += template.format( + target=f'\'{str(path)}\'', + pyx_files=str(pyx), + pxd_files=str(pxd), + py_files=str(py), + data_files=str(data) + ) + + # add subdir entries + contents += '\n' + for subdir in subdirs: + contents += f'subdir(\'{subdir.name}\')\n' + + return contents + + +if __name__ == '__main__': + generate_meson_files(PACKAGES) \ No newline at end of file diff --git a/dev/install_editable.sh b/dev/install_editable.sh new file mode 100755 index 00000000..15c73653 --- /dev/null +++ b/dev/install_editable.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e # exit if an error occurs + +echo Installing package as editable... +python -m pip install --config-settings=editable-verbose=true --no-build-isolation --upgrade --editable . \ No newline at end of file diff --git a/dev/notes/building_bdist_with_manylinux.txt b/dev/notes/building_bdist_with_manylinux.txt index 68b83f4c..569d65b1 100644 --- a/dev/notes/building_bdist_with_manylinux.txt +++ b/dev/notes/building_bdist_with_manylinux.txt @@ -13,10 +13,11 @@ Start the manylinux docker container (this will download the container, mount th This will drop you into the manylinux container terminal. The /opt/python folder in the container holds the various versions of python. This example targets python 3.7. Adjust the paths as appropriate to build bdists for different python versions. cd io/source - /opt/python/cp37-cp37m/bin/python -m pip build . - auditwheel repair dist/raysect-0.8.1-cp37-cp37m-linux_x86_64.whl --plat manylinux2010_x86_64 + /opt/python/cp37-cp37m/bin/python -m pip install cython numpy==1.14.6 + /opt/python/cp37-cp37m/bin/python setup.py bdist_wheel + auditwheel repair dist/raysect-0.8.2-cp37-cp37m-linux_x86_64.whl --plat manylinux2010_x86_64 -This will compile the wheel and repair any library references to produce the manylinux wheel files in a folder ./wheelhouse. e.g. raysect-0.8.1-cp37-cp37m-manylinux1_x86_64.whl and raysect-0.8.1-cp37-cp37m-manylinux2010_x86_64.whl. +This will compile the wheel and repair any library references to produce the manylinux wheel files in a folder ./wheelhouse. e.g. raysect-0.8.2-cp37-cp37m-manylinux1_x86_64.whl and raysect-0.8.2-cp37-cp37m-manylinux2010_x86_64.whl. These can then be uploaded to pypi. diff --git a/dev/root-meson.build b/dev/root-meson.build new file mode 100644 index 00000000..a3034a21 --- /dev/null +++ b/dev/root-meson.build @@ -0,0 +1,15 @@ +project('raysect', 'cython', + default_options: ['python.install-env=auto'], + version: run_command(['dev/build/update_version.sh'], check: true).stdout().strip() +) + +# when building a distribution, copy the dynamically generated _version.py to the distribution folder +meson.add_dist_script('dev/build/add_version_file_to_dist.sh') + +py = import('python').find_installation(pure: false) +numpy = dependency('numpy', method: 'config-tool') +fs = import('fs') + +# disabling explicit noexcept until pycharm fixes their cython 3 support (causes a large number of build warnings) +cython_args = ['--annotate', '-X legacy_implicit_noexcept=True'] +cython_dependencies = [numpy] diff --git a/dev/subdir-meson.build b/dev/subdir-meson.build new file mode 100644 index 00000000..951e96c0 --- /dev/null +++ b/dev/subdir-meson.build @@ -0,0 +1,25 @@ +target_path = {target} + +# source files +py_files = {py_files} +pyx_files = {pyx_files} +pxd_files = {pxd_files} +data_files = {data_files} + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) diff --git a/dev/templates/template.py b/dev/templates/template.py index 287daa1d..61f12ff5 100644 --- a/dev/templates/template.py +++ b/dev/templates/template.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2018, , Raysect Project +# Copyright (c) 2014-2025, , Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/docs/source/api_reference/primitives/geometric_primitives.rst b/docs/source/api_reference/primitives/geometric_primitives.rst index d0b833cb..a21d2b87 100644 --- a/docs/source/api_reference/primitives/geometric_primitives.rst +++ b/docs/source/api_reference/primitives/geometric_primitives.rst @@ -21,3 +21,7 @@ Geometric Primitives .. autoclass:: raysect.primitive.Parabola :members: radius, height :show-inheritance: + +.. autoclass:: raysect.primitive.Torus + :members: major_radius, minor_radius + :show-inheritance: diff --git a/docs/source/conf.py b/docs/source/conf.py index d99fdd5f..206b8bf6 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -52,7 +52,7 @@ # General information about the project. project = 'Raysect' -copyright = '2014-2023, Dr Alex Meakins' +copyright = '2014-2025, Dr Alex Meakins' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/docs/source/how_it_works.rst b/docs/source/how_it_works.rst index d64f5916..ef6994ff 100644 --- a/docs/source/how_it_works.rst +++ b/docs/source/how_it_works.rst @@ -58,7 +58,7 @@ Primitives Scenes in Raysect consist of primitives, which are the basic objects making up the scene. These are objects that rays can interact with, e.g light sources, lenses, mirrors, diffuse surfaces. Types of primitives: -* Mathematically defined surfaces and solids (i.e. sphere, box, cylinder, cone). +* Mathematically defined surfaces and solids (i.e. sphere, box, cylinder, cone, parabola, torus). * Constructive Solid Geometry Operators (union, intersect, subtract). * Tri-poly meshes optimised for millions of polygons, support instancing. Importers for STL and OBJ. diff --git a/docs/source/images/raysect_primitives.png b/docs/source/images/raysect_primitives.png index 0439ab93..cd2301f3 100644 Binary files a/docs/source/images/raysect_primitives.png and b/docs/source/images/raysect_primitives.png differ diff --git a/docs/source/primitives.rst b/docs/source/primitives.rst index ac997661..1a94b7ae 100644 --- a/docs/source/primitives.rst +++ b/docs/source/primitives.rst @@ -3,7 +3,7 @@ Primitives ********** -The raysect primitives: sphere; box; cylinder; and cone. +The raysect primitives: sphere; box; cylinder; cone; parabola; and torus. .. image:: images/raysect_primitives.png :align: center @@ -30,6 +30,15 @@ Cone .. autoclass:: raysect.primitive.Cone +Parabola +~~~~~~~~ + +.. autoclass:: raysect.primitive.Parabola + +Torus +~~~~~ + +.. autoclass:: raysect.primitive.Torus ============== CSG Operations diff --git a/meson.build b/meson.build new file mode 100644 index 00000000..62bcf36f --- /dev/null +++ b/meson.build @@ -0,0 +1,20 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/root-meson.build. + +project('raysect', 'cython', + default_options: ['python.install-env=auto'], + version: run_command(['dev/build/update_version.sh'], check: true).stdout().strip() +) + +# when building a distribution, copy the dynamically generated _version.py to the distribution folder +meson.add_dist_script('dev/build/add_version_file_to_dist.sh') + +py = import('python').find_installation(pure: false) +numpy = dependency('numpy', method: 'config-tool') +fs = import('fs') + +# disabling explicit noexcept until pycharm fixes their cython 3 support (causes a large number of build warnings) +cython_args = ['--annotate', '-X legacy_implicit_noexcept=True'] +cython_dependencies = [numpy] + +subdir('raysect') diff --git a/pyproject.toml b/pyproject.toml index 17d821e2..4998820c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,34 @@ +[project] +name = "raysect" +requires-python = ">=3.9" +authors = [{name = "Dr Alex Meakins et al.", email = "developers@raysect.org"}] +description = "A Ray-tracing Framework for Science and Engineering" +readme = {file = "README.md", content-type = "text/markdown"} +license = "BSD-3-Clause" +license-files = ["LICENSE.txt"] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Science/Research", + "Intended Audience :: Education", + "Intended Audience :: Developers", + "Natural Language :: English", + "Operating System :: POSIX :: Linux", + "Programming Language :: Cython", + "Programming Language :: Python :: 3", + "Topic :: Multimedia :: Graphics :: 3D Rendering", + "Topic :: Scientific/Engineering :: Physics" +] +dynamic = ["version"] + +[project.urls] +Homepage = "https://www.raysect.org" +Repository = "https://github.com/raysect/source" +Issues = "https://github.com/raysect/source/issues" +Changelog = "https://github.com/raysect/source/blob/master/CHANGELOG.txt" + [build-system] -requires = ["setuptools>=42.0", "wheel", "oldest-supported-numpy", "cython>=0.28,<3.0"] -build-backend = "setuptools.build_meta" +requires = ["meson-python", "setuptools", "wheel", "numpy", "cython>=3.1", "setuptools-scm"] +build-backend = "mesonpy" + +[tool.setuptools_scm] +version_file = "raysect/_version.py" \ No newline at end of file diff --git a/raysect/VERSION b/raysect/VERSION deleted file mode 100644 index 4978240f..00000000 --- a/raysect/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.8.1.post1 \ No newline at end of file diff --git a/raysect/__init__.py b/raysect/__init__.py index 55f2d163..27213b8b 100644 --- a/raysect/__init__.py +++ b/raysect/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -27,8 +27,4 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -from os import path as _path - -# parse the package version number -with open(_path.join(_path.dirname(__file__), 'VERSION')) as _f: - __version__ = _f.read().strip() +from ._version import * diff --git a/raysect/core/__init__.pxd b/raysect/core/__init__.pxd index 0a52110d..ab2ff0f0 100644 --- a/raysect/core/__init__.pxd +++ b/raysect/core/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/__init__.py b/raysect/core/__init__.py index 20ff3a5c..40ce3a2a 100644 --- a/raysect/core/__init__.py +++ b/raysect/core/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/acceleration/__init__.pxd b/raysect/core/acceleration/__init__.pxd index 5c646ab1..d46af06d 100644 --- a/raysect/core/acceleration/__init__.pxd +++ b/raysect/core/acceleration/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/acceleration/__init__.py b/raysect/core/acceleration/__init__.py index e26d57f7..d6e69eb3 100644 --- a/raysect/core/acceleration/__init__.py +++ b/raysect/core/acceleration/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/acceleration/accelerator.pxd b/raysect/core/acceleration/accelerator.pxd index 994b82bb..495d3051 100644 --- a/raysect/core/acceleration/accelerator.pxd +++ b/raysect/core/acceleration/accelerator.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -33,10 +33,9 @@ from raysect.core.ray cimport Ray from raysect.core.math cimport Point3D from raysect.core.intersection cimport Intersection + cdef class Accelerator: cpdef build(self, list primitives) - cpdef Intersection hit(self, Ray ray) - cpdef list contains(self, Point3D point) diff --git a/raysect/core/acceleration/accelerator.pyx b/raysect/core/acceleration/accelerator.pyx index 45493f01..e6279d91 100644 --- a/raysect/core/acceleration/accelerator.pyx +++ b/raysect/core/acceleration/accelerator.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,13 +32,10 @@ cdef class Accelerator: cpdef build(self, list primitives): - pass cpdef Intersection hit(self, Ray ray): - raise NotImplementedError("Accelerator virtual method hit() has not been implemented.") cpdef list contains(self, Point3D point): - raise NotImplementedError("Accelerator virtual method contains() has not been implemented.") \ No newline at end of file diff --git a/raysect/core/acceleration/boundprimitive.pxd b/raysect/core/acceleration/boundprimitive.pxd index a1bb52a3..cec01939 100644 --- a/raysect/core/acceleration/boundprimitive.pxd +++ b/raysect/core/acceleration/boundprimitive.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -37,12 +37,11 @@ from raysect.core.intersection cimport Intersection cdef class BoundPrimitive: - cdef readonly Primitive primitive - cdef readonly BoundingBox3D box - cdef bint _primitive_tested + cdef: + readonly Primitive primitive + readonly BoundingBox3D box + bint _primitive_tested cdef Intersection hit(self, Ray ray) - cdef Intersection next_intersection(self) - cdef bint contains(self, Point3D point) \ No newline at end of file diff --git a/raysect/core/acceleration/boundprimitive.pyx b/raysect/core/acceleration/boundprimitive.pyx index f312aa2a..277ae192 100644 --- a/raysect/core/acceleration/boundprimitive.pyx +++ b/raysect/core/acceleration/boundprimitive.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/acceleration/kdtree.pxd b/raysect/core/acceleration/kdtree.pxd index a6a9290d..16d0612d 100644 --- a/raysect/core/acceleration/kdtree.pxd +++ b/raysect/core/acceleration/kdtree.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -33,12 +33,15 @@ from raysect.core.acceleration.accelerator cimport Accelerator as _Accelerator from raysect.core.math.spatial.kdtree3d cimport KDTree3DCore as _KDTreeCore from raysect.core.intersection cimport Intersection + cdef class _PrimitiveKDTree(_KDTreeCore): + cdef: list primitives Intersection hit_intersection cdef class KDTree(_Accelerator): + cdef _PrimitiveKDTree _kdtree diff --git a/raysect/core/acceleration/kdtree.pyx b/raysect/core/acceleration/kdtree.pyx index 6631e546..2d7b28df 100644 --- a/raysect/core/acceleration/kdtree.pyx +++ b/raysect/core/acceleration/kdtree.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -154,7 +154,6 @@ cdef class _PrimitiveKDTree(_KDTreeCore): # dereference the primitives and check if they contain the point enclosing_primitives = [] for item in range(count): - index = self._nodes[id].items[item] primitive = self.primitives[index] if primitive.contains(point): diff --git a/raysect/core/acceleration/meson.build b/raysect/core/acceleration/meson.build new file mode 100644 index 00000000..ccd50d7c --- /dev/null +++ b/raysect/core/acceleration/meson.build @@ -0,0 +1,30 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/acceleration' + +# source files +py_files = ['__init__.py'] +pyx_files = ['accelerator.pyx', 'boundprimitive.pyx', 'kdtree.pyx', 'unaccelerated.pyx'] +pxd_files = ['__init__.pxd', 'accelerator.pxd', 'boundprimitive.pxd', 'kdtree.pxd', 'unaccelerated.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('tests') diff --git a/raysect/core/acceleration/tests/meson.build b/raysect/core/acceleration/tests/meson.build new file mode 100644 index 00000000..53eb7130 --- /dev/null +++ b/raysect/core/acceleration/tests/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/acceleration/tests' + +# source files +py_files = ['__init__.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/core/acceleration/unaccelerated.pxd b/raysect/core/acceleration/unaccelerated.pxd index f951e0e6..d9ce0979 100644 --- a/raysect/core/acceleration/unaccelerated.pxd +++ b/raysect/core/acceleration/unaccelerated.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -35,5 +35,6 @@ from raysect.core.boundingbox cimport BoundingBox3D cdef class Unaccelerated(Accelerator): - cdef list primitives - cdef BoundingBox3D world_box + cdef: + list primitives + BoundingBox3D world_box diff --git a/raysect/core/acceleration/unaccelerated.pyx b/raysect/core/acceleration/unaccelerated.pyx index 293828e7..c07e407f 100644 --- a/raysect/core/acceleration/unaccelerated.pyx +++ b/raysect/core/acceleration/unaccelerated.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -37,6 +37,7 @@ from raysect.core.math cimport Point3D from raysect.core.intersection cimport Intersection from raysect.core.acceleration.boundprimitive cimport BoundPrimitive + cdef class Unaccelerated(Accelerator): def __init__(self): @@ -54,7 +55,6 @@ cdef class Unaccelerated(Accelerator): self.world_box = BoundingBox3D() for primitive in primitives: - accel_primitive = BoundPrimitive(primitive) self.primitives.append(accel_primitive) self.world_box.union(accel_primitive.box) @@ -70,23 +70,17 @@ cdef class Unaccelerated(Accelerator): # does the ray intersect the space containing the primitives if not self.world_box.hit(ray): - return None # find the closest primitive-ray intersection closest_intersection = None - # intial search distance is maximum possible ray extent + # initial search distance is maximum possible ray extent distance = ray.max_distance - for primitive in self.primitives: - intersection = primitive.hit(ray) - if intersection is not None: - if intersection.ray_distance < distance: - distance = intersection.ray_distance closest_intersection = intersection @@ -101,15 +95,12 @@ cdef class Unaccelerated(Accelerator): BoundPrimitive primitive if not self.world_box.contains(point): - return [] enclosing_primitives = [] for primitive in self.primitives: - if primitive.contains(point): - enclosing_primitives.append(primitive.primitive) return enclosing_primitives \ No newline at end of file diff --git a/raysect/core/boundingbox.pxd b/raysect/core/boundingbox.pxd index 8528a587..29167b96 100644 --- a/raysect/core/boundingbox.pxd +++ b/raysect/core/boundingbox.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -40,37 +40,21 @@ cdef class BoundingBox3D: cdef Point3D upper cdef Point3D get_centre(self) - cpdef bint hit(self, Ray ray) - cpdef tuple full_intersection(self, Ray ray) - cdef bint intersect(self, Ray ray, double *front_intersection, double *back_intersection) - cdef void _slab(self, double origin, double direction, double lower, double upper, double *front_intersection, double *back_intersection) nogil - cpdef bint contains(self, Point3D point) - cpdef object union(self, BoundingBox3D box) - cpdef object extend(self, Point3D point, double padding=*) - cpdef double surface_area(self) - cpdef double volume(self) - cpdef list vertices(self) - cpdef double extent(self, int axis) except -1 - cpdef int largest_axis(self) - cpdef double largest_extent(self) - cpdef object pad(self, double padding) - cpdef object pad_axis(self, int axis, double padding) - cpdef BoundingSphere3D enclosing_sphere(self) @@ -95,23 +79,14 @@ cdef class BoundingBox2D: cdef Point2D upper cpdef bint contains(self, Point2D point) - cpdef object union(self, BoundingBox2D box) - cpdef object extend(self, Point2D point, double padding=*) - cpdef double surface_area(self) - cpdef list vertices(self) - cpdef double extent(self, int axis) except -1 - cpdef int largest_axis(self) - cpdef double largest_extent(self) - cpdef object pad(self, double padding) - cpdef object pad_axis(self, int axis, double padding) diff --git a/raysect/core/boundingbox.pyx b/raysect/core/boundingbox.pyx index eb616121..5c54fc41 100644 --- a/raysect/core/boundingbox.pyx +++ b/raysect/core/boundingbox.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,18 +32,19 @@ # TODO: add docstrings cimport cython +from libc.math cimport INFINITY from raysect.core.math cimport new_point3d, new_point2d -# cython doesn't have a built-in infinity constant, this compiles to +infinity -DEF INFINITY = 1e999 # axis defines -DEF X_AXIS = 0 -DEF Y_AXIS = 1 -DEF Z_AXIS = 2 +cdef enum: + X_AXIS = 0 + Y_AXIS = 1 + Z_AXIS = 2 + # defines the padding on the sphere which encloses the BoundingBox3D. -DEF SPHERE_PADDING = 1.000001 +cdef const double SPHERE_PADDING = 1.000001 @cython.freelist(256) @@ -258,6 +259,7 @@ cdef class BoundingBox3D: return False if (point.z < self.lower.z) or (point.z > self.upper.z): return False + return True cpdef object union(self, BoundingBox3D box): diff --git a/raysect/core/boundingsphere.pxd b/raysect/core/boundingsphere.pxd index 3d8c743a..821bea48 100644 --- a/raysect/core/boundingsphere.pxd +++ b/raysect/core/boundingsphere.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -39,19 +39,11 @@ cdef class BoundingSphere3D: Point3D centre cpdef bint hit(self, Ray ray) - cpdef tuple full_intersection(self, Ray ray) - cdef bint intersect(self, Ray ray, double *front_intersection, double *back_intersection) - cpdef bint contains(self, Point3D point) - cpdef object union(self, BoundingSphere3D sphere) - cpdef object extend(self, Point3D point, double padding=*) - cpdef double surface_area(self) - cpdef double volume(self) - cpdef object pad(self, double padding) diff --git a/raysect/core/boundingsphere.pyx b/raysect/core/boundingsphere.pyx index 91d2a0ac..ce65cb2a 100644 --- a/raysect/core/boundingsphere.pyx +++ b/raysect/core/boundingsphere.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/constants.py b/raysect/core/constants.py index 34e03e09..d3b539b1 100644 --- a/raysect/core/constants.py +++ b/raysect/core/constants.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/containers.pxd b/raysect/core/containers.pxd index 1f81042f..3de638c5 100644 --- a/raysect/core/containers.pxd +++ b/raysect/core/containers.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -46,22 +46,16 @@ cdef class LinkedList: _Item last cpdef bint is_empty(self) - cpdef add(self, object value) - cpdef add_items(self, object iterable) - cpdef object get_index(self, int index) - cpdef insert(self, object value, int index) - cpdef object remove(self, int index) cdef class Stack(LinkedList): cpdef push(self, object value) - cpdef object pop(self) diff --git a/raysect/core/containers.pyx b/raysect/core/containers.pyx index 31880c65..ae93ac83 100644 --- a/raysect/core/containers.pyx +++ b/raysect/core/containers.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/intersection.pxd b/raysect/core/intersection.pxd index e0bd5336..ae11253b 100644 --- a/raysect/core/intersection.pxd +++ b/raysect/core/intersection.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/intersection.pyx b/raysect/core/intersection.pyx index d65373bc..70cad491 100644 --- a/raysect/core/intersection.pyx +++ b/raysect/core/intersection.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,6 +31,7 @@ cimport cython + @cython.freelist(256) cdef class Intersection: """ diff --git a/raysect/core/material.pxd b/raysect/core/material.pxd index 79b0c18c..d61f1553 100644 --- a/raysect/core/material.pxd +++ b/raysect/core/material.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/material.pyx b/raysect/core/material.pyx index 8b89e811..5d4342bd 100644 --- a/raysect/core/material.pyx +++ b/raysect/core/material.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/__init__.pxd b/raysect/core/math/__init__.pxd index c6157f8f..6d31a123 100644 --- a/raysect/core/math/__init__.pxd +++ b/raysect/core/math/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/__init__.py b/raysect/core/math/__init__.py index b7f368b2..9482e2b4 100644 --- a/raysect/core/math/__init__.py +++ b/raysect/core/math/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/_mat4.pxd b/raysect/core/math/_mat4.pxd index 96027a05..40d34ff1 100644 --- a/raysect/core/math/_mat4.pxd +++ b/raysect/core/math/_mat4.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -34,10 +34,7 @@ cdef class _Mat4: cdef double m[4][4] cdef double get_element(self, int row, int column) - cdef void set_element(self, int row, int column, double v) - cpdef bint is_identity(self, double tolerance=*) - cpdef bint is_close(self, _Mat4 other, double tolerance=*) diff --git a/raysect/core/math/_mat4.pyx b/raysect/core/math/_mat4.pyx index 3c30c820..4c5c775b 100644 --- a/raysect/core/math/_mat4.pyx +++ b/raysect/core/math/_mat4.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -54,7 +54,6 @@ cdef class _Mat4: # special handling for _Mat4 if isinstance(v, _Mat4): - m = <_Mat4>v for i in range(0, 4): for j in range(0, 4): @@ -95,7 +94,6 @@ cdef class _Mat4: Expects a tuple (row, column) as the index. e.g. v = matrix[1, 2] - """ cdef int row, column diff --git a/raysect/core/math/_vec3.pxd b/raysect/core/math/_vec3.pxd index 89da3338..df241982 100644 --- a/raysect/core/math/_vec3.pxd +++ b/raysect/core/math/_vec3.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,16 +32,10 @@ cdef class _Vec3: cdef public double x, y, z - cpdef double dot(self, _Vec3 v) - cpdef double angle(self, _Vec3 v) - cdef double get_length(self) nogil - cdef object set_length(self, double v) - cdef double get_index(self, int index) nogil - cdef void set_index(self, int index, double value) nogil diff --git a/raysect/core/math/_vec3.pyx b/raysect/core/math/_vec3.pyx index bab25d55..02c16bd4 100644 --- a/raysect/core/math/_vec3.pyx +++ b/raysect/core/math/_vec3.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -58,8 +58,8 @@ cdef class _Vec3: return self.y elif i == 2: return self.z - else: - raise IndexError("Index out of range [0, 2].") + + raise IndexError("Index out of range [0, 2].") def __setitem__(self, int i, double value): """Sets the vector coordinates by index ([0,1,2] -> [x,y,z]).""" @@ -74,6 +74,7 @@ cdef class _Vec3: raise IndexError("Index out of range [0, 2].") def __iter__(self): + yield self.x yield self.y yield self.z @@ -189,8 +190,8 @@ cdef class _Vec3: return self.y elif index == 2: return self.z - else: - return NAN + + return NAN cdef void set_index(self, int index, double value) nogil: """ diff --git a/raysect/core/math/affinematrix.pxd b/raysect/core/math/affinematrix.pxd index de6b6c26..abbfe35d 100644 --- a/raysect/core/math/affinematrix.pxd +++ b/raysect/core/math/affinematrix.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -35,7 +35,6 @@ from raysect.core.math._mat4 cimport _Mat4 cdef class AffineMatrix3D(_Mat4): cpdef AffineMatrix3D inverse(self) - cdef AffineMatrix3D mul(self, AffineMatrix3D m) diff --git a/raysect/core/math/affinematrix.pyx b/raysect/core/math/affinematrix.pyx index ff729f75..f585d199 100644 --- a/raysect/core/math/affinematrix.pyx +++ b/raysect/core/math/affinematrix.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -33,7 +33,6 @@ cimport cython from libc.math cimport fabs - cdef class AffineMatrix3D(_Mat4): """A 4x4 affine matrix. @@ -133,7 +132,7 @@ cdef class AffineMatrix3D(_Mat4): s += ", " return s + "])" - def __mul__(object x, object y): + def __mul__(self, object y): """Multiplication operator. >>> from raysect.core import translate, rotate_x @@ -146,26 +145,28 @@ cdef class AffineMatrix3D(_Mat4): cdef AffineMatrix3D mx, my - if isinstance(x, AffineMatrix3D) and isinstance(y, AffineMatrix3D): + if isinstance(y, AffineMatrix3D): - mx = x + mx = self my = y - return new_affinematrix3d(mx.m[0][0] * my.m[0][0] + mx.m[0][1] * my.m[1][0] + mx.m[0][2] * my.m[2][0] + mx.m[0][3] * my.m[3][0], - mx.m[0][0] * my.m[0][1] + mx.m[0][1] * my.m[1][1] + mx.m[0][2] * my.m[2][1] + mx.m[0][3] * my.m[3][1], - mx.m[0][0] * my.m[0][2] + mx.m[0][1] * my.m[1][2] + mx.m[0][2] * my.m[2][2] + mx.m[0][3] * my.m[3][2], - mx.m[0][0] * my.m[0][3] + mx.m[0][1] * my.m[1][3] + mx.m[0][2] * my.m[2][3] + mx.m[0][3] * my.m[3][3], - mx.m[1][0] * my.m[0][0] + mx.m[1][1] * my.m[1][0] + mx.m[1][2] * my.m[2][0] + mx.m[1][3] * my.m[3][0], - mx.m[1][0] * my.m[0][1] + mx.m[1][1] * my.m[1][1] + mx.m[1][2] * my.m[2][1] + mx.m[1][3] * my.m[3][1], - mx.m[1][0] * my.m[0][2] + mx.m[1][1] * my.m[1][2] + mx.m[1][2] * my.m[2][2] + mx.m[1][3] * my.m[3][2], - mx.m[1][0] * my.m[0][3] + mx.m[1][1] * my.m[1][3] + mx.m[1][2] * my.m[2][3] + mx.m[1][3] * my.m[3][3], - mx.m[2][0] * my.m[0][0] + mx.m[2][1] * my.m[1][0] + mx.m[2][2] * my.m[2][0] + mx.m[2][3] * my.m[3][0], - mx.m[2][0] * my.m[0][1] + mx.m[2][1] * my.m[1][1] + mx.m[2][2] * my.m[2][1] + mx.m[2][3] * my.m[3][1], - mx.m[2][0] * my.m[0][2] + mx.m[2][1] * my.m[1][2] + mx.m[2][2] * my.m[2][2] + mx.m[2][3] * my.m[3][2], - mx.m[2][0] * my.m[0][3] + mx.m[2][1] * my.m[1][3] + mx.m[2][2] * my.m[2][3] + mx.m[2][3] * my.m[3][3], - mx.m[3][0] * my.m[0][0] + mx.m[3][1] * my.m[1][0] + mx.m[3][2] * my.m[2][0] + mx.m[3][3] * my.m[3][0], - mx.m[3][0] * my.m[0][1] + mx.m[3][1] * my.m[1][1] + mx.m[3][2] * my.m[2][1] + mx.m[3][3] * my.m[3][1], - mx.m[3][0] * my.m[0][2] + mx.m[3][1] * my.m[1][2] + mx.m[3][2] * my.m[2][2] + mx.m[3][3] * my.m[3][2], - mx.m[3][0] * my.m[0][3] + mx.m[3][1] * my.m[1][3] + mx.m[3][2] * my.m[2][3] + mx.m[3][3] * my.m[3][3]) + return new_affinematrix3d( + mx.m[0][0] * my.m[0][0] + mx.m[0][1] * my.m[1][0] + mx.m[0][2] * my.m[2][0] + mx.m[0][3] * my.m[3][0], + mx.m[0][0] * my.m[0][1] + mx.m[0][1] * my.m[1][1] + mx.m[0][2] * my.m[2][1] + mx.m[0][3] * my.m[3][1], + mx.m[0][0] * my.m[0][2] + mx.m[0][1] * my.m[1][2] + mx.m[0][2] * my.m[2][2] + mx.m[0][3] * my.m[3][2], + mx.m[0][0] * my.m[0][3] + mx.m[0][1] * my.m[1][3] + mx.m[0][2] * my.m[2][3] + mx.m[0][3] * my.m[3][3], + mx.m[1][0] * my.m[0][0] + mx.m[1][1] * my.m[1][0] + mx.m[1][2] * my.m[2][0] + mx.m[1][3] * my.m[3][0], + mx.m[1][0] * my.m[0][1] + mx.m[1][1] * my.m[1][1] + mx.m[1][2] * my.m[2][1] + mx.m[1][3] * my.m[3][1], + mx.m[1][0] * my.m[0][2] + mx.m[1][1] * my.m[1][2] + mx.m[1][2] * my.m[2][2] + mx.m[1][3] * my.m[3][2], + mx.m[1][0] * my.m[0][3] + mx.m[1][1] * my.m[1][3] + mx.m[1][2] * my.m[2][3] + mx.m[1][3] * my.m[3][3], + mx.m[2][0] * my.m[0][0] + mx.m[2][1] * my.m[1][0] + mx.m[2][2] * my.m[2][0] + mx.m[2][3] * my.m[3][0], + mx.m[2][0] * my.m[0][1] + mx.m[2][1] * my.m[1][1] + mx.m[2][2] * my.m[2][1] + mx.m[2][3] * my.m[3][1], + mx.m[2][0] * my.m[0][2] + mx.m[2][1] * my.m[1][2] + mx.m[2][2] * my.m[2][2] + mx.m[2][3] * my.m[3][2], + mx.m[2][0] * my.m[0][3] + mx.m[2][1] * my.m[1][3] + mx.m[2][2] * my.m[2][3] + mx.m[2][3] * my.m[3][3], + mx.m[3][0] * my.m[0][0] + mx.m[3][1] * my.m[1][0] + mx.m[3][2] * my.m[2][0] + mx.m[3][3] * my.m[3][0], + mx.m[3][0] * my.m[0][1] + mx.m[3][1] * my.m[1][1] + mx.m[3][2] * my.m[2][1] + mx.m[3][3] * my.m[3][1], + mx.m[3][0] * my.m[0][2] + mx.m[3][1] * my.m[1][2] + mx.m[3][2] * my.m[2][2] + mx.m[3][3] * my.m[3][2], + mx.m[3][0] * my.m[0][3] + mx.m[3][1] * my.m[1][3] + mx.m[3][2] * my.m[2][3] + mx.m[3][3] * my.m[3][3] + ) return NotImplemented @@ -231,38 +232,42 @@ cdef class AffineMatrix3D(_Mat4): t[16] = self.m[1][1] * self.m[3][3] - self.m[1][3] * self.m[3][1] t[17] = self.m[1][2] * self.m[3][3] - self.m[1][3] * self.m[3][2] - return new_affinematrix3d((self.m[2][2] * t[16] - self.m[2][1] * t[17] - self.m[2][3] * t[15]) * idet, - (self.m[2][1] * t[11] - self.m[2][2] * t[10] + self.m[2][3] * t[ 9]) * idet, - (self.m[3][1] * t[ 5] - self.m[3][2] * t[ 4] + self.m[3][3] * t[ 3]) * idet, - -t[21] * idet, - (self.m[2][0] * t[17] - self.m[2][2] * t[14] + self.m[2][3] * t[13]) * idet, - (self.m[2][2] * t[ 8] - self.m[2][0] * t[11] - self.m[2][3] * t[ 7]) * idet, - (self.m[3][2] * t[ 2] - self.m[3][0] * t[ 5] - self.m[3][3] * t[ 1]) * idet, - t[20] * idet, - (self.m[2][1] * t[14] - self.m[2][0] * t[16] - self.m[2][3] * t[12]) * idet, - (self.m[2][0] * t[10] - self.m[2][1] * t[ 8] + self.m[2][3] * t[ 6]) * idet, - (self.m[3][0] * t[ 4] - self.m[3][1] * t[ 2] + self.m[3][3] * t[ 0]) * idet, - -t[19] * idet, - (self.m[2][0] * t[15] - self.m[2][1] * t[13] + self.m[2][2] * t[12]) * idet, - (self.m[2][1] * t[ 7] - self.m[2][0] * t[ 9] - self.m[2][2] * t[ 6]) * idet, - (self.m[3][1] * t[ 1] - self.m[3][0] * t[ 3] - self.m[3][2] * t[ 0]) * idet, - t[18] * idet) + return new_affinematrix3d( + (self.m[2][2] * t[16] - self.m[2][1] * t[17] - self.m[2][3] * t[15]) * idet, + (self.m[2][1] * t[11] - self.m[2][2] * t[10] + self.m[2][3] * t[ 9]) * idet, + (self.m[3][1] * t[ 5] - self.m[3][2] * t[ 4] + self.m[3][3] * t[ 3]) * idet, + -t[21] * idet, + (self.m[2][0] * t[17] - self.m[2][2] * t[14] + self.m[2][3] * t[13]) * idet, + (self.m[2][2] * t[ 8] - self.m[2][0] * t[11] - self.m[2][3] * t[ 7]) * idet, + (self.m[3][2] * t[ 2] - self.m[3][0] * t[ 5] - self.m[3][3] * t[ 1]) * idet, + t[20] * idet, + (self.m[2][1] * t[14] - self.m[2][0] * t[16] - self.m[2][3] * t[12]) * idet, + (self.m[2][0] * t[10] - self.m[2][1] * t[ 8] + self.m[2][3] * t[ 6]) * idet, + (self.m[3][0] * t[ 4] - self.m[3][1] * t[ 2] + self.m[3][3] * t[ 0]) * idet, + -t[19] * idet, + (self.m[2][0] * t[15] - self.m[2][1] * t[13] + self.m[2][2] * t[12]) * idet, + (self.m[2][1] * t[ 7] - self.m[2][0] * t[ 9] - self.m[2][2] * t[ 6]) * idet, + (self.m[3][1] * t[ 1] - self.m[3][0] * t[ 3] - self.m[3][2] * t[ 0]) * idet, + t[18] * idet + ) cdef AffineMatrix3D mul(self, AffineMatrix3D m): - return new_affinematrix3d(self.m[0][0] * m.m[0][0] + self.m[0][1] * m.m[1][0] + self.m[0][2] * m.m[2][0] + self.m[0][3] * m.m[3][0], - self.m[0][0] * m.m[0][1] + self.m[0][1] * m.m[1][1] + self.m[0][2] * m.m[2][1] + self.m[0][3] * m.m[3][1], - self.m[0][0] * m.m[0][2] + self.m[0][1] * m.m[1][2] + self.m[0][2] * m.m[2][2] + self.m[0][3] * m.m[3][2], - self.m[0][0] * m.m[0][3] + self.m[0][1] * m.m[1][3] + self.m[0][2] * m.m[2][3] + self.m[0][3] * m.m[3][3], - self.m[1][0] * m.m[0][0] + self.m[1][1] * m.m[1][0] + self.m[1][2] * m.m[2][0] + self.m[1][3] * m.m[3][0], - self.m[1][0] * m.m[0][1] + self.m[1][1] * m.m[1][1] + self.m[1][2] * m.m[2][1] + self.m[1][3] * m.m[3][1], - self.m[1][0] * m.m[0][2] + self.m[1][1] * m.m[1][2] + self.m[1][2] * m.m[2][2] + self.m[1][3] * m.m[3][2], - self.m[1][0] * m.m[0][3] + self.m[1][1] * m.m[1][3] + self.m[1][2] * m.m[2][3] + self.m[1][3] * m.m[3][3], - self.m[2][0] * m.m[0][0] + self.m[2][1] * m.m[1][0] + self.m[2][2] * m.m[2][0] + self.m[2][3] * m.m[3][0], - self.m[2][0] * m.m[0][1] + self.m[2][1] * m.m[1][1] + self.m[2][2] * m.m[2][1] + self.m[2][3] * m.m[3][1], - self.m[2][0] * m.m[0][2] + self.m[2][1] * m.m[1][2] + self.m[2][2] * m.m[2][2] + self.m[2][3] * m.m[3][2], - self.m[2][0] * m.m[0][3] + self.m[2][1] * m.m[1][3] + self.m[2][2] * m.m[2][3] + self.m[2][3] * m.m[3][3], - self.m[3][0] * m.m[0][0] + self.m[3][1] * m.m[1][0] + self.m[3][2] * m.m[2][0] + self.m[3][3] * m.m[3][0], - self.m[3][0] * m.m[0][1] + self.m[3][1] * m.m[1][1] + self.m[3][2] * m.m[2][1] + self.m[3][3] * m.m[3][1], - self.m[3][0] * m.m[0][2] + self.m[3][1] * m.m[1][2] + self.m[3][2] * m.m[2][2] + self.m[3][3] * m.m[3][2], - self.m[3][0] * m.m[0][3] + self.m[3][1] * m.m[1][3] + self.m[3][2] * m.m[2][3] + self.m[3][3] * m.m[3][3]) + return new_affinematrix3d( + self.m[0][0] * m.m[0][0] + self.m[0][1] * m.m[1][0] + self.m[0][2] * m.m[2][0] + self.m[0][3] * m.m[3][0], + self.m[0][0] * m.m[0][1] + self.m[0][1] * m.m[1][1] + self.m[0][2] * m.m[2][1] + self.m[0][3] * m.m[3][1], + self.m[0][0] * m.m[0][2] + self.m[0][1] * m.m[1][2] + self.m[0][2] * m.m[2][2] + self.m[0][3] * m.m[3][2], + self.m[0][0] * m.m[0][3] + self.m[0][1] * m.m[1][3] + self.m[0][2] * m.m[2][3] + self.m[0][3] * m.m[3][3], + self.m[1][0] * m.m[0][0] + self.m[1][1] * m.m[1][0] + self.m[1][2] * m.m[2][0] + self.m[1][3] * m.m[3][0], + self.m[1][0] * m.m[0][1] + self.m[1][1] * m.m[1][1] + self.m[1][2] * m.m[2][1] + self.m[1][3] * m.m[3][1], + self.m[1][0] * m.m[0][2] + self.m[1][1] * m.m[1][2] + self.m[1][2] * m.m[2][2] + self.m[1][3] * m.m[3][2], + self.m[1][0] * m.m[0][3] + self.m[1][1] * m.m[1][3] + self.m[1][2] * m.m[2][3] + self.m[1][3] * m.m[3][3], + self.m[2][0] * m.m[0][0] + self.m[2][1] * m.m[1][0] + self.m[2][2] * m.m[2][0] + self.m[2][3] * m.m[3][0], + self.m[2][0] * m.m[0][1] + self.m[2][1] * m.m[1][1] + self.m[2][2] * m.m[2][1] + self.m[2][3] * m.m[3][1], + self.m[2][0] * m.m[0][2] + self.m[2][1] * m.m[1][2] + self.m[2][2] * m.m[2][2] + self.m[2][3] * m.m[3][2], + self.m[2][0] * m.m[0][3] + self.m[2][1] * m.m[1][3] + self.m[2][2] * m.m[2][3] + self.m[2][3] * m.m[3][3], + self.m[3][0] * m.m[0][0] + self.m[3][1] * m.m[1][0] + self.m[3][2] * m.m[2][0] + self.m[3][3] * m.m[3][0], + self.m[3][0] * m.m[0][1] + self.m[3][1] * m.m[1][1] + self.m[3][2] * m.m[2][1] + self.m[3][3] * m.m[3][1], + self.m[3][0] * m.m[0][2] + self.m[3][1] * m.m[1][2] + self.m[3][2] * m.m[2][2] + self.m[3][3] * m.m[3][2], + self.m[3][0] * m.m[0][3] + self.m[3][1] * m.m[1][3] + self.m[3][2] * m.m[2][3] + self.m[3][3] * m.m[3][3] + ) diff --git a/raysect/core/math/cython/__init__.pxd b/raysect/core/math/cython/__init__.pxd index cab00413..acf269ad 100644 --- a/raysect/core/math/cython/__init__.pxd +++ b/raysect/core/math/cython/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/cython/__init__.py b/raysect/core/math/cython/__init__.py index 72563a6a..09d9347b 100644 --- a/raysect/core/math/cython/__init__.py +++ b/raysect/core/math/cython/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/cython/interpolation/__init__.pxd b/raysect/core/math/cython/interpolation/__init__.pxd index 194028db..88a141b7 100644 --- a/raysect/core/math/cython/interpolation/__init__.pxd +++ b/raysect/core/math/cython/interpolation/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/cython/interpolation/cubic.pxd b/raysect/core/math/cython/interpolation/cubic.pxd index 6a6472ae..d73a25b3 100644 --- a/raysect/core/math/cython/interpolation/cubic.pxd +++ b/raysect/core/math/cython/interpolation/cubic.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/cython/interpolation/cubic.pyx b/raysect/core/math/cython/interpolation/cubic.pyx index af96c5a2..d8c55ea4 100644 --- a/raysect/core/math/cython/interpolation/cubic.pyx +++ b/raysect/core/math/cython/interpolation/cubic.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/cython/interpolation/helper/.meson-exclude b/raysect/core/math/cython/interpolation/helper/.meson-exclude new file mode 100644 index 00000000..e69de29b diff --git a/raysect/core/math/cython/interpolation/helper/code_generator.py b/raysect/core/math/cython/interpolation/helper/code_generator.py index be809e48..4b43aecf 100644 --- a/raysect/core/math/cython/interpolation/helper/code_generator.py +++ b/raysect/core/math/cython/interpolation/helper/code_generator.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/cython/interpolation/helper/equation.py b/raysect/core/math/cython/interpolation/helper/equation.py index fa462101..4d7cd31d 100644 --- a/raysect/core/math/cython/interpolation/helper/equation.py +++ b/raysect/core/math/cython/interpolation/helper/equation.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/cython/interpolation/linear.pxd b/raysect/core/math/cython/interpolation/linear.pxd index 2fd510bc..2dcfff26 100644 --- a/raysect/core/math/cython/interpolation/linear.pxd +++ b/raysect/core/math/cython/interpolation/linear.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/cython/interpolation/linear.pyx b/raysect/core/math/cython/interpolation/linear.pyx index 31a3772b..772eed3e 100644 --- a/raysect/core/math/cython/interpolation/linear.pyx +++ b/raysect/core/math/cython/interpolation/linear.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/cython/interpolation/meson.build b/raysect/core/math/cython/interpolation/meson.build new file mode 100644 index 00000000..aa0d8393 --- /dev/null +++ b/raysect/core/math/cython/interpolation/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/cython/interpolation' + +# source files +py_files = [] +pyx_files = ['cubic.pyx', 'linear.pyx'] +pxd_files = ['__init__.pxd', 'cubic.pxd', 'linear.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/core/math/cython/meson.build b/raysect/core/math/cython/meson.build new file mode 100644 index 00000000..4efc6066 --- /dev/null +++ b/raysect/core/math/cython/meson.build @@ -0,0 +1,31 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/cython' + +# source files +py_files = ['__init__.py'] +pyx_files = ['tetrahedra.pyx', 'transform.pyx', 'triangle.pyx', 'utility.pyx'] +pxd_files = ['__init__.pxd', 'tetrahedra.pxd', 'transform.pxd', 'triangle.pxd', 'utility.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('interpolation') +subdir('tests') diff --git a/raysect/core/math/cython/tests/meson.build b/raysect/core/math/cython/tests/meson.build new file mode 100644 index 00000000..126d42a0 --- /dev/null +++ b/raysect/core/math/cython/tests/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/cython/tests' + +# source files +py_files = ['__init__.py', 'test_tetrahedra.py', 'test_triangle.py', 'test_utility.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/core/math/cython/tests/test_tetrahedra.py b/raysect/core/math/cython/tests/test_tetrahedra.py index 20190be3..cf168060 100644 --- a/raysect/core/math/cython/tests/test_tetrahedra.py +++ b/raysect/core/math/cython/tests/test_tetrahedra.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/cython/tests/test_triangle.py b/raysect/core/math/cython/tests/test_triangle.py index ec694eaf..ed3d40de 100644 --- a/raysect/core/math/cython/tests/test_triangle.py +++ b/raysect/core/math/cython/tests/test_triangle.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/cython/tests/test_utility.py b/raysect/core/math/cython/tests/test_utility.py index 26032987..3d9f5fc0 100644 --- a/raysect/core/math/cython/tests/test_utility.py +++ b/raysect/core/math/cython/tests/test_utility.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/cython/tetrahedra.pxd b/raysect/core/math/cython/tetrahedra.pxd index 2ab8e297..2818fe19 100644 --- a/raysect/core/math/cython/tetrahedra.pxd +++ b/raysect/core/math/cython/tetrahedra.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/cython/tetrahedra.pyx b/raysect/core/math/cython/tetrahedra.pyx index ce1d781e..7ed1af96 100644 --- a/raysect/core/math/cython/tetrahedra.pyx +++ b/raysect/core/math/cython/tetrahedra.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/cython/transform.pxd b/raysect/core/math/cython/transform.pxd index bf0393e7..2a6a08cf 100644 --- a/raysect/core/math/cython/transform.pxd +++ b/raysect/core/math/cython/transform.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/cython/transform.pyx b/raysect/core/math/cython/transform.pyx index a0ad2136..68b27df8 100644 --- a/raysect/core/math/cython/transform.pyx +++ b/raysect/core/math/cython/transform.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/cython/triangle.pxd b/raysect/core/math/cython/triangle.pxd index 0ced0f58..1530798c 100644 --- a/raysect/core/math/cython/triangle.pxd +++ b/raysect/core/math/cython/triangle.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,16 +31,16 @@ cdef bint inside_triangle(double v1x, double v1y, double v2x, double v2y, - double v3x, double v3y, double px, double py) nogil + double v3x, double v3y, double px, double py) nogil cdef void barycentric_coords(double v1x, double v1y, double v2x, double v2y, - double v3x, double v3y, double px, double py, - double *alpha, double *beta, double *gamma) nogil + double v3x, double v3y, double px, double py, + double *alpha, double *beta, double *gamma) nogil cdef bint barycentric_inside_triangle(double alpha, double beta, double gamma) nogil cdef double barycentric_interpolation(double alpha, double beta, double gamma, - double va, double vb, double vc) nogil + double va, double vb, double vc) nogil diff --git a/raysect/core/math/cython/triangle.pyx b/raysect/core/math/cython/triangle.pyx index 3ff34bcf..8e3c5ecb 100644 --- a/raysect/core/math/cython/triangle.pyx +++ b/raysect/core/math/cython/triangle.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -33,7 +33,7 @@ cimport cython cdef bint inside_triangle(double v1x, double v1y, double v2x, double v2y, - double v3x, double v3y, double px, double py) nogil: + double v3x, double v3y, double px, double py) nogil: """ Cython utility for testing if point is inside a triangle. @@ -52,8 +52,7 @@ cdef bint inside_triangle(double v1x, double v1y, double v2x, double v2y, :rtype: bool """ - cdef: - double ux, uy, vx, vy + cdef double ux, uy, vx, vy # calculate vectors ux = v2x - v1x @@ -158,7 +157,7 @@ cdef bint barycentric_inside_triangle(double alpha, double beta, double gamma) n cdef double barycentric_interpolation(double alpha, double beta, double gamma, - double va, double vb, double vc) nogil: + double va, double vb, double vc) nogil: """ Cython utility for interpolation of data at triangle vertices. diff --git a/raysect/core/math/cython/utility.pxd b/raysect/core/math/cython/utility.pxd index 4574e39c..71cc0303 100644 --- a/raysect/core/math/cython/utility.pxd +++ b/raysect/core/math/cython/utility.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,6 +31,8 @@ cimport cython +DEF EQN_EPS = 1.0e-9 + cdef int find_index(double[::1] x, double v) nogil cdef double interpolate(double[::1] x, double[::1] y, double p) nogil @@ -64,12 +66,42 @@ cdef inline void swap_int(int *a, int *b) nogil: a[0] = b[0] b[0] = temp +cdef inline void sort_three_doubles(double *a, double *b, double *c) nogil: + if a[0] > b[0]: + swap_double(a, b) + if b[0] > c[0]: + swap_double(b, c) + if a[0] > c[0]: + swap_double(a, c) + +cdef inline void sort_four_doubles(double *a, double *b, double *c, double *d) nogil: + if a[0] > b[0]: + swap_double(a, b) + if b[0] > c[0]: + swap_double(b, c) + if c[0] > d[0]: + swap_double(c, d) + if a[0] > b[0]: + swap_double(a, b) + if b[0] > c[0]: + swap_double(b, c) + if a[0] > b[0]: + swap_double(a, b) + +cdef inline bint is_zero(double v) nogil: + return v < EQN_EPS and v > -EQN_EPS + @cython.cdivision(True) cdef inline double lerp(double x0, double x1, double y0, double y1, double x) nogil: return ((y1 - y0) / (x1 - x0)) * (x - x0) + y0 cdef bint solve_quadratic(double a, double b, double c, double *t0, double *t1) nogil +cdef int solve_cubic(double a, double b, double c, double d, double *t0, double *t1, double *t2) nogil + +cdef int solve_quartic(double a, double b, double c, double d, double e, + double *t0, double *t1, double *t2, double *t3) nogil + cdef bint winding2d(double[:,::1] vertices) nogil cdef bint point_inside_polygon(double[:,::1] vertices, double ptx, double pty) diff --git a/raysect/core/math/cython/utility.pyx b/raysect/core/math/cython/utility.pyx index 38f4d761..a0cd8b32 100644 --- a/raysect/core/math/cython/utility.pyx +++ b/raysect/core/math/cython/utility.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -from libc.math cimport sqrt +from libc.math cimport sqrt, fabs, cbrt, acos, cos, M_PI cimport cython #TODO: Write unit tests! @@ -114,8 +114,7 @@ cdef double interpolate(double[::1] x, double[::1] y, double p) nogil: :rtype: double """ - cdef: - int index, top_index + cdef int index, top_index index = find_index(x, p) @@ -202,7 +201,6 @@ cdef double integrate(double[::1] x, double[::1] y, double x0, double x1) nogil: else: integral_sum = 0.0 - if lower_index == 0: # add contribution from point below array @@ -382,16 +380,16 @@ cdef bint solve_quadratic(double a, double b, double c, double *t0, double *t1) The a, b and c arguments are the three constants of the quadratic equation: f = a.x^2 + b.x^2 + c - + If the quadratic equation has 1 or 2 real roots, this function will return True. If there are no real roots this method will return False. - + The values of the real roots, are returned by setting the values of the memory locations pointed to by t0 and t1. In the case of a single root, both t0 and t1 will have the same value. If there are not roots, the values - of t0 and t1 will be undefined. + of t0 and t1 will be undefined. - :param double a: Quadratic constant. + :param double a: Quadratic constant. :param double b: Quadratic constant. :param double c: Quadratic constant. :param double t0: 1st root of the quadratic. @@ -421,6 +419,334 @@ cdef bint solve_quadratic(double a, double b, double c, double *t0, double *t1) return True +@cython.cdivision(True) +cdef int solve_cubic(double a, double b, double c, double d, double *t0, double *t1, double *t2) nogil: + """ + Calculates the roots of a cubic equation. + + The a, b, c and d arguments are the four constants of the cubic equation: + + f = a.x^3 + b.x^2 + c.x + d + + The cubic equation has 1, 2 or 3 real roots, and this function returns either 1 or 3, but in a special case, + 2 of the 3 roots found by this function will be equal to each other up to machine epsilon. + + + The values of the roots, are returned by setting the values of the memory locations pointed to by t0, t1, and t2. + + In the case of three real roots, the roots themselves back in t0, t1 and t2. + In the case of two real roots, a pair in t0, t1, and t2 will have the same value, and the other is a different one. + In the case of one real root, t0 will be the real root, and t1 +- i * t2 will a pair of complex-conjugated roots. + + The practical algorithm is followed by https://quarticequations.com + + :param double a: Cubic constant. + :param double b: Cubic constant. + :param double c: Cubic constant. + :param double d: Cubic constant. + :param double t0: 1st real root. + :param double t1: either 2nd real root or real part of coplex-conjugated roots. + :param double t2: either 3rd real root or imaginary part of coplex-conjugated roots. + :return: Number of real roots. + :rtype: int + """ + cdef: + double q, r, sq_b, cb_q, D, A, z0, phi, u + + # normal form: x^3 + bx^2 + cx + d = 0 + b /= a + c /= a + d /= a + + # convert depressed cubic: y^3 + 3qy - 2r = 0 + sq_b = b * b + q = (3.0 * c - sq_b) / 9.0 + r = (c * b - 3.0 * d) / 6.0 - b * sq_b / 27.0 + + # calculate discriminant + cb_q = q * q * q + D = cb_q + r * r + + # one real root and a pair of complex-conjugate roots + if D > 0: + A = cbrt(fabs(r) + sqrt(D)) + if r < 0: + z0 = q / A - A + else: + z0 = A - q / A + + t0[0] = z0 - b / 3.0 + t1[0] = -0.5 * z0 - b / 3.0 + t2[0] = 0.5 * sqrt(3.0) * (A + q / A) + + return 1 + + # Trigonometric solution for three real roots + else: + if is_zero(q): + phi = 0.0 + + # otherwise q < 0 because of D = q^3 + r^2 < 0 + else: + phi = acos(r / sqrt(-cb_q)) / 3.0 + + u = 2.0 * sqrt(-q) + + t0[0] = u * cos(phi) - b / 3.0 + t1[0] = -u * cos(phi + M_PI / 3.0) - b / 3.0 + t2[0] = -u * cos(phi - M_PI / 3.0) - b / 3.0 + + return 3 + + +cdef int solve_biquadratic(double a, double c, double e, double *t0, double *t1, double *t2, double *t3) nogil: + """ + Calculate the real roots of a bi quadratic equation. + + The a, c, and e arguments are the 3 constants of the biquadratic equation: + + f = a.x^4 + c.x^2 + e + + The biquadratic equation has 0, 2, or 4 real roots, and this function will return the number of real roots. + + The values of the real roots, are returned by setting the values of the + memory locations pointed to by t0, t1, t2, and t3. If there are two or four real roots, + the values of t2 and t3 will be undefined. If there is no real root, + all values will be undefined. + + :param double a: Biquadratic constant. + :param double c: Biquadratic constant. + :param double e: Biquadratic constant. + :param double t0: 1st root of the biquadratic. + :param double t1: 2nd root of the biquadratic. + :param double t2: 3rd root of the biquadratic. + :param double t3: 4th root of the biquadratic. + :return: Number of real roots. + :rtype: int + """ + cdef double s0, s1, sx0, sx1 + + # solve quadratic for x^2 + if not solve_quadratic(a, c, e, &s0, &s1): + return 0 + + # ensure s0 < s1 + if s0 > s1: + swap_double(&s0, &s1) + + # 0 <= s0 <= s1, 4 real roots + if s0 >= 0: + sx0 = sqrt(s0) + sx1 = sqrt(s1) + t0[0] = -sx1 + t1[0] = -sx0 + t2[0] = sx0 + t3[0] = sx1 + return 4 + + # s0 < 0 <= s1, 2 real roots + elif s1 >= 0: + sx1 = sqrt(s1) + t0[0] = -sx1 + t1[0] = sx1 + return 2 + + # s0 < s1 <= 0, no real root + else: + return 0 + + +cdef int _solve_depressed_quartic(double p, double q, double r, double *t0, double *t1, double *t2, double *t3) nogil: + """ + Solve depressed quartic: x^4 + p.x^2 + q.x + r + """ + cdef: + int num + double s0, sigma, A, B, sq_A, sq_B + + if q > 0: + sigma = 1.0 + else: + sigma = -1.0 + + # q = 0 => x^4 + p.x^2 + r = 0 + if is_zero(q): + return solve_biquadratic(1.0, p, r, t0, t1, t2, t3) + + # solve resolvent cubic: t^3 - 2pt^2 + (p^2-4r)t + q^2 = 0 + # using Van der Waerden's method + num = solve_cubic(1.0, -2.0 * p, p * p - 4.0 * r, q * q, t0, t1, t2) + + if num > 1: + # sort roots to t0 < t1 < t2 + sort_three_doubles(t0, t1, t2) + + # t0 <= 0 => t1*t2 >= 0 because vieta's therem: -t0*t1*t2 = q^2 + if t0[0] <= 0: + s0 = sqrt(-t0[0]) + A = -t1[0] - t2[0] - 2.0 * sigma * sqrt(t1[0] * t2[0]) + B = -t1[0] - t2[0] + 2.0 * sigma * sqrt(t1[0] * t2[0]) + + # four real roots + if A >= 0 and B >= 0: + sq_A = sqrt(A) + sq_B = sqrt(B) + t0[0] = 0.5 * (s0 + sq_A) + t1[0] = 0.5 * (s0 - sq_A) + t2[0] = 0.5 * (-s0 + sq_B) + t3[0] = 0.5 * (-s0 - sq_B) + return 4 + + # two real roots + elif A < 0 and B >= 0: + sq_B = sqrt(B) + t0[0] = 0.5 * (-s0 + sq_B) + t1[0] = 0.5 * (-s0 - sq_B) + return 2 + + # two real roots + elif A >= 0 and B < 0: + sq_A = sqrt(A) + t0[0] = 0.5 * (s0 + sq_A) + t1[0] = 0.5 * (s0 - sq_A) + return 2 + + # no real root + else: + return 0 + + # if resolvent cubic solutions have only one real root t0 + else: + if t0[0] <= 0: + s0 = sqrt(-t0[0]) + A = -2.0 * t1[0] - 2.0 * sigma * sqrt(t1[0] * t1[0] + t2[0] * t2[0]) + B = -2.0 * t1[0] + 2.0 * sigma * sqrt(t1[0] * t1[0] + t2[0] * t2[0]) + + # four real roots + if A >= 0 and B >= 0: + sq_A = sqrt(A) + sq_B = sqrt(B) + t0[0] = 0.5 * (s0 + sq_A) + t1[0] = 0.5 * (s0 - sq_A) + t2[0] = 0.5 * (-s0 + sq_B) + t3[0] = 0.5 * (-s0 - sq_B) + return 4 + + # two real roots + elif A < 0 and B >= 0: + sq_B = sqrt(B) + t0[0] = 0.5 * (-s0 + sq_B) + t1[0] = 0.5 * (-s0 - sq_B) + return 2 + + # two real roots + elif A >= 0 and B < 0: + sq_A = sqrt(A) + t0[0] = 0.5 * (s0 + sq_A) + t1[0] = 0.5 * (s0 - sq_A) + return 2 + + # no real root + else: + return 0 + + # no real root if -t0 < 0 + return 0 + + +@cython.cdivision(True) +cdef void one_newton_step(double b, double c, double d, double e, double *x) nogil: + """ + One step Newton's method for monic quartic polinomial: x^4 + b.x^3 + c.x^2 * d.x + e = 0 + + :param double b: Qurtic constant. + :param double c: Qurtic constant. + :param double d: Qurtic constant. + :param double e: Qurtic constant. + :param double x: one root of the quartic. + """ + cdef double fx, dfx + dfx = ((4.0 * x[0] + 3 * b) * x[0] + 2.0 * d) * x[0] + e + if not is_zero(dfx): + fx = (((x[0] + b) * x[0] + c) * x[0] + d) * x[0] + e + x[0] = x[0] - fx / dfx + + +@cython.cdivision(True) +cdef int solve_quartic(double a, double b, double c, double d, double e, + double *t0, double *t1, double *t2, double *t3) nogil: + """ + Calculates the real roots of a quartic equation with Van der Waerden method. + + The a, b, c, d and e arguments are the five constants of the quartic equation: + + f = a.x^4 + b.x^3 + c.x^2 + d.x + e + + The quartic equation has 0, 1, 2, 3 or 4 real roots, and this function will return the number of real roots. + + The values of the real roots, are returned by setting the values of the + memory locations pointed to by t0, t1, t2, and t3. If there are one or two real roots, + the values of t2 and t3 will be undefined. If there is no real root, + all values will be undefined. + + The practical algorithm of Van der Waerden method is followed by https://quarticequations.com + + :param double a: Qurtic constant. + :param double b: Qurtic constant. + :param double c: Qurtic constant. + :param double d: Qurtic constant. + :param double e: Qurtic constant. + :param double t0: 1st root of the quartic. + :param double t1: 2nd root of the quartic. + :param double t2: 3rd root of the quartic. + :param double t3: 4th root of the quartic. + :return: Number of real roots. + :rtype: int + """ + cdef: + double p, q, r, sq_b + int cubic_num, num = 0 + + # normal form: x^4 + bx^3 + cx^2 + dx + e = 0 + b /= a + c /= a + d /= a + e /= a + + # substitute x = y - b / 4 to eliminate quadric term: y^4 + py^2 + qy + r = 0 + sq_b = b * b + p = c - 3 * sq_b / 8.0 + q = sq_b * b / 8.0 - 0.5 * b * c + d + r = -3.0 * sq_b * sq_b / 256.0 + sq_b * c / 16.0 - b * d / 4.0 + e + + if is_zero(r): + # no absolute term: y(y^3 + py + q) = 0 + t0[0] = 0 + cubic_num = solve_cubic(1.0, 0.0, p, q, t1, t2, t3) + num = 1 + cubic_num + + else: + # solve depressed quartic + num = _solve_depressed_quartic(p, q, r, t0, t1, t2, t3) + + # resubstitute + t0[0] -= b / 4.0 + t1[0] -= b / 4.0 + t2[0] -= b / 4.0 + t3[0] -= b / 4.0 + + # One newton step for each real root + if num > 0: + one_newton_step(b, c, d, e, t0) + one_newton_step(b, c, d, e, t1) + if num > 2: + one_newton_step(b, c, d, e, t2) + if num > 3: + one_newton_step(b, c, d, e, t3) + + return num + + @cython.boundscheck(False) @cython.wraparound(False) cdef bint winding2d(double[:,::1] vertices) nogil: @@ -540,3 +866,26 @@ def _test_winding2d(p): def _point_inside_polygon(vertices, ptx, pty): """Expose cython function for testing.""" return point_inside_polygon(vertices, ptx, pty) + + +def _solve_cubic(a, b, c, d): + """Expose cython function for testing.""" + t0 = 0.0 + t1 = 0.0 + t2 = 0.0 + num = 0.0 + num = solve_cubic(a, b, c, d, &t0, &t1, &t2) + + return (t0, t1, t2, num) + + +def _solve_quartic(a, b, c, d, e): + """Expose cython function for testing.""" + t0 = 0.0 + t1 = 0.0 + t2 = 0.0 + t3 = 0.0 + num = 0.0 + num = solve_quartic(a, b, c, d, e, &t0, &t1, &t2, &t3) + + return (t0, t1, t2, t3, num) diff --git a/raysect/core/math/function/__init__.pxd b/raysect/core/math/function/__init__.pxd index 05892ec9..fc9bb6f8 100644 --- a/raysect/core/math/function/__init__.pxd +++ b/raysect/core/math/function/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/__init__.py b/raysect/core/math/function/__init__.py index 1f86dc02..f1547852 100644 --- a/raysect/core/math/function/__init__.py +++ b/raysect/core/math/function/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/base.pxd b/raysect/core/math/function/base.pxd index 7c5496c9..97114480 100644 --- a/raysect/core/math/function/base.pxd +++ b/raysect/core/math/function/base.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/base.pyx b/raysect/core/math/function/base.pyx index 1651a2b8..eea199ce 100644 --- a/raysect/core/math/function/base.pyx +++ b/raysect/core/math/function/base.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/__init__.pxd b/raysect/core/math/function/float/__init__.pxd index 3ea77d80..d91e9872 100644 --- a/raysect/core/math/function/float/__init__.pxd +++ b/raysect/core/math/function/float/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/__init__.py b/raysect/core/math/function/float/__init__.py index a034c18f..3342550d 100644 --- a/raysect/core/math/function/float/__init__.py +++ b/raysect/core/math/function/float/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/base.pxd b/raysect/core/math/function/float/base.pxd index 9571ba2d..fb029145 100644 --- a/raysect/core/math/function/float/base.pxd +++ b/raysect/core/math/function/float/base.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/base.pyx b/raysect/core/math/function/float/base.pyx index 044ceb05..638cb60b 100644 --- a/raysect/core/math/function/float/base.pyx +++ b/raysect/core/math/function/float/base.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/__init__.pxd b/raysect/core/math/function/float/function1d/__init__.pxd index 4af50056..2ed50c15 100644 --- a/raysect/core/math/function/float/function1d/__init__.pxd +++ b/raysect/core/math/function/float/function1d/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/__init__.py b/raysect/core/math/function/float/function1d/__init__.py index 0f95ba5b..f37b334a 100644 --- a/raysect/core/math/function/float/function1d/__init__.py +++ b/raysect/core/math/function/float/function1d/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/arg.pxd b/raysect/core/math/function/float/function1d/arg.pxd index ded7841d..f5ca173d 100644 --- a/raysect/core/math/function/float/function1d/arg.pxd +++ b/raysect/core/math/function/float/function1d/arg.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/arg.pyx b/raysect/core/math/function/float/function1d/arg.pyx index d45ee931..d01de920 100644 --- a/raysect/core/math/function/float/function1d/arg.pyx +++ b/raysect/core/math/function/float/function1d/arg.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/autowrap.pxd b/raysect/core/math/function/float/function1d/autowrap.pxd index bd874ad1..3b0cee4c 100644 --- a/raysect/core/math/function/float/function1d/autowrap.pxd +++ b/raysect/core/math/function/float/function1d/autowrap.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/autowrap.pyx b/raysect/core/math/function/float/function1d/autowrap.pyx index a00f0f9d..f0df595f 100644 --- a/raysect/core/math/function/float/function1d/autowrap.pyx +++ b/raysect/core/math/function/float/function1d/autowrap.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/base.pxd b/raysect/core/math/function/float/function1d/base.pxd index 4a037f29..c900a3bc 100644 --- a/raysect/core/math/function/float/function1d/base.pxd +++ b/raysect/core/math/function/float/function1d/base.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/base.pyx b/raysect/core/math/function/float/function1d/base.pyx index 2426f3cd..7695fc99 100644 --- a/raysect/core/math/function/float/function1d/base.pyx +++ b/raysect/core/math/function/float/function1d/base.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -65,110 +65,161 @@ cdef class Function1D(FloatFunction): def __repr__(self): return 'Function1D(x)' - def __add__(object a, object b): - if is_callable(a): - if is_callable(b): - # a() + b() - return AddFunction1D(a, b) - elif isinstance(b, numbers.Real): - # a() + B -> B + a() - return AddScalar1D( b, a) - elif isinstance(a, numbers.Real): - if is_callable(b): - # A + b() - return AddScalar1D( a, b) + def __add__(self, object b): + + if is_callable(b): + # a() + b() + return AddFunction1D(self, b) + + elif isinstance(b, numbers.Real): + # a() + B -> B + a() + return AddScalar1D( b, self) + return NotImplemented + + def __radd__(self, object a): + return self.__add__(a) + + def __sub__(self, object b): + + if is_callable(b): + # a() - b() + return SubtractFunction1D(self, b) + + elif isinstance(b, numbers.Real): + # a() - B -> -B + a() + return AddScalar1D(-( b), self) - def __sub__(object a, object b): - if is_callable(a): - if is_callable(b): - # a() - b() - return SubtractFunction1D(a, b) - elif isinstance(b, numbers.Real): - # a() - B -> -B + a() - return AddScalar1D(-( b), a) - elif isinstance(a, numbers.Real): - if is_callable(b): - # A - b() - return SubtractScalar1D( a, b) return NotImplemented + + def __rsub__(self, object a): - def __mul__(object a, object b): if is_callable(a): - if is_callable(b): - # a() * b() - return MultiplyFunction1D(a, b) - elif isinstance(b, numbers.Real): - # a() * B -> B * a() - return MultiplyScalar1D( b, a) + # a() - b() + return SubtractFunction1D(a, self) + elif isinstance(a, numbers.Real): - if is_callable(b): - # A * b() - return MultiplyScalar1D( a, b) + # A - b() + return SubtractScalar1D( a, self) + return NotImplemented + def __mul__(self, object b): + + if is_callable(b): + # a() * b() + return MultiplyFunction1D(self, b) + + elif isinstance(b, numbers.Real): + # a() * B -> B * a() + return MultiplyScalar1D( b, self) + + return NotImplemented + + def __rmul__(self, object a): + return self.__mul__(a) + @cython.cdivision(True) - def __truediv__(object a, object b): + def __truediv__(self, object b): + cdef double v + + if is_callable(b): + # a() / b() + return DivideFunction1D(self, b) + + elif isinstance(b, numbers.Real): + # a() / B -> 1/B * a() + v = b + if v == 0.0: + raise ZeroDivisionError("Scalar used as the denominator of the division is zero valued.") + return MultiplyScalar1D(1 / v, self) + + return NotImplemented + + def __rtruediv__(self, object a): + if is_callable(a): - if is_callable(b): - # a() / b() - return DivideFunction1D(a, b) - elif isinstance(b, numbers.Real): - # a() / B -> 1/B * a() - v = b - if v == 0.0: - raise ZeroDivisionError("Scalar used as the denominator of the division is zero valued.") - return MultiplyScalar1D(1/v, a) + # a() / b() + return DivideFunction1D(a, self) + elif isinstance(a, numbers.Real): - if is_callable(b): - # A * b() - return DivideScalar1D( a, b) + # A / b() + return DivideScalar1D( a, self) + return NotImplemented - def __mod__(object a, object b): + def __mod__(self, object b): + cdef double v + + if is_callable(b): + # a() % b() + return ModuloFunction1D(self, b) + + elif isinstance(b, numbers.Real): + # a() % B + v = b + if v == 0.0: + raise ZeroDivisionError("Scalar used as the divisor of the division is zero valued.") + return ModuloFunctionScalar1D(self, v) + + return NotImplemented + + def __rmod__(self, object a): + if is_callable(a): - if is_callable(b): - # a() % b() - return ModuloFunction1D(a, b) - elif isinstance(b, numbers.Real): - # a() % B - v = b - if v == 0.0: - raise ZeroDivisionError("Scalar used as the divisor of the division is zero valued.") - return ModuloFunctionScalar1D(a, v) + # a() % b() + return ModuloFunction1D(a, self) + elif isinstance(a, numbers.Real): - if is_callable(b): - # A % b() - return ModuloScalarFunction1D( a, b) + # A % b() + return ModuloScalarFunction1D( a, self) + return NotImplemented def __neg__(self): return MultiplyScalar1D(-1, self) - def __pow__(object a, object b, object c): + def __pow__(self, object b, object c): + if c is not None: # Optimised implementation of pow(a, b, c) not available: fall back # to general implementation - return (a ** b) % c + return PowFunction1D(self, b) % c + + if is_callable(b): + # a() ** b() + return PowFunction1D(self, b) + + elif isinstance(b, numbers.Real): + # a() ** b + return PowFunctionScalar1D(self, b) + + return NotImplemented + + def __rpow__(self, object a, object c): + + if c is not None: + # Optimised implementation of pow(a, b, c) not available: fall back + # to general implementation + return PowFunction1D(a, self) % c + if is_callable(a): - if is_callable(b): - # a() ** b() - return PowFunction1D(a, b) - elif isinstance(b, numbers.Real): - # a() ** b - return PowFunctionScalar1D(a, b) + # a() ** b() + return PowFunction1D(a, self) + elif isinstance(a, numbers.Real): - if is_callable(b): - # a ** b() - return PowScalarFunction1D( a, b) + # A ** b() + return PowScalarFunction1D( a, self) + return NotImplemented def __abs__(self): return AbsFunction1D(self) def __richcmp__(self, object other, int op): + if is_callable(other): if op == Py_EQ: return EqualsFunction1D(self, other) @@ -182,6 +233,7 @@ cdef class Function1D(FloatFunction): return LessEqualsFunction1D(self, other) if op == Py_GE: return GreaterEqualsFunction1D(self, other) + if isinstance(other, numbers.Real): if op == Py_EQ: return EqualsScalar1D( other, self) @@ -199,6 +251,7 @@ cdef class Function1D(FloatFunction): if op == Py_GE: # f() >= K -> K <= f return LessEqualsScalar1D( other, self) + return NotImplemented diff --git a/raysect/core/math/function/float/function1d/blend.pxd b/raysect/core/math/function/float/function1d/blend.pxd index 430b61db..7face450 100644 --- a/raysect/core/math/function/float/function1d/blend.pxd +++ b/raysect/core/math/function/float/function1d/blend.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/blend.pyx b/raysect/core/math/function/float/function1d/blend.pyx index 85264a15..7c8bb844 100644 --- a/raysect/core/math/function/float/function1d/blend.pyx +++ b/raysect/core/math/function/float/function1d/blend.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/cmath.pxd b/raysect/core/math/function/float/function1d/cmath.pxd index 73b35f7d..95007bc3 100644 --- a/raysect/core/math/function/float/function1d/cmath.pxd +++ b/raysect/core/math/function/float/function1d/cmath.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/cmath.pyx b/raysect/core/math/function/float/function1d/cmath.pyx index c9b4dac2..e557eb98 100644 --- a/raysect/core/math/function/float/function1d/cmath.pyx +++ b/raysect/core/math/function/float/function1d/cmath.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/constant.pxd b/raysect/core/math/function/float/function1d/constant.pxd index 1910e4d5..df5fbbd9 100644 --- a/raysect/core/math/function/float/function1d/constant.pxd +++ b/raysect/core/math/function/float/function1d/constant.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/constant.pyx b/raysect/core/math/function/float/function1d/constant.pyx index 68894b40..715e8d5c 100644 --- a/raysect/core/math/function/float/function1d/constant.pyx +++ b/raysect/core/math/function/float/function1d/constant.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/interpolate.pxd b/raysect/core/math/function/float/function1d/interpolate.pxd index 0e03eaab..e54dbb27 100644 --- a/raysect/core/math/function/float/function1d/interpolate.pxd +++ b/raysect/core/math/function/float/function1d/interpolate.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/interpolate.pyx b/raysect/core/math/function/float/function1d/interpolate.pyx index 30ee5cd8..49a11c36 100644 --- a/raysect/core/math/function/float/function1d/interpolate.pyx +++ b/raysect/core/math/function/float/function1d/interpolate.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/meson.build b/raysect/core/math/function/float/function1d/meson.build new file mode 100644 index 00000000..ab3dc6d2 --- /dev/null +++ b/raysect/core/math/function/float/function1d/meson.build @@ -0,0 +1,30 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/float/function1d' + +# source files +py_files = ['__init__.py'] +pyx_files = ['arg.pyx', 'autowrap.pyx', 'base.pyx', 'blend.pyx', 'cmath.pyx', 'constant.pyx', 'interpolate.pyx', 'samplers.pyx'] +pxd_files = ['__init__.pxd', 'arg.pxd', 'autowrap.pxd', 'base.pxd', 'blend.pxd', 'cmath.pxd', 'constant.pxd', 'interpolate.pxd', 'samplers.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('tests') diff --git a/raysect/core/math/function/float/function1d/samplers.pxd b/raysect/core/math/function/float/function1d/samplers.pxd index d0cbf99a..9d186b24 100644 --- a/raysect/core/math/function/float/function1d/samplers.pxd +++ b/raysect/core/math/function/float/function1d/samplers.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/samplers.pyx b/raysect/core/math/function/float/function1d/samplers.pyx index 0fbd5c8e..e17f5439 100644 --- a/raysect/core/math/function/float/function1d/samplers.pyx +++ b/raysect/core/math/function/float/function1d/samplers.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -35,6 +35,7 @@ from .autowrap cimport autowrap_function1d cimport cython cimport numpy as np + @cython.boundscheck(False) @cython.wraparound(False) cpdef tuple sample1d(object function, double x_min, double x_max, int x_samples): @@ -58,7 +59,6 @@ cpdef tuple sample1d(object function, double x_min, double x_max, int x_samples) if x_samples < 1: raise ValueError("The argument x_samples must be >= 1") - # ensures that func is of type Function1D. I.e. if 'function' argument was Python function, it'll get autowrapped # into Function1D object func = autowrap_function1d(function) diff --git a/raysect/core/math/function/float/function1d/tests/data/meson.build b/raysect/core/math/function/float/function1d/tests/data/meson.build new file mode 100644 index 00000000..54664e7b --- /dev/null +++ b/raysect/core/math/function/float/function1d/tests/data/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/float/function1d/tests/data' + +# source files +py_files = ['interpolator1d_test_data.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/core/math/function/float/function1d/tests/meson.build b/raysect/core/math/function/float/function1d/tests/meson.build new file mode 100644 index 00000000..d6cc6d57 --- /dev/null +++ b/raysect/core/math/function/float/function1d/tests/meson.build @@ -0,0 +1,30 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/float/function1d/tests' + +# source files +py_files = ['__init__.py', 'test_arg.py', 'test_autowrap.py', 'test_base.py', 'test_cmath.py', 'test_constant.py', 'test_interpolator.py', 'test_samplers.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('data') diff --git a/raysect/core/math/function/float/function1d/tests/scripts/.meson-exclude b/raysect/core/math/function/float/function1d/tests/scripts/.meson-exclude new file mode 100644 index 00000000..e69de29b diff --git a/raysect/core/math/function/float/function1d/tests/scripts/generate_1d_splines.py b/raysect/core/math/function/float/function1d/tests/scripts/generate_1d_splines.py index b5bccabf..80d96548 100644 --- a/raysect/core/math/function/float/function1d/tests/scripts/generate_1d_splines.py +++ b/raysect/core/math/function/float/function1d/tests/scripts/generate_1d_splines.py @@ -1,5 +1,5 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/tests/test_arg.py b/raysect/core/math/function/float/function1d/tests/test_arg.py index 9bdac4bd..95b1c4e5 100644 --- a/raysect/core/math/function/float/function1d/tests/test_arg.py +++ b/raysect/core/math/function/float/function1d/tests/test_arg.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/tests/test_autowrap.py b/raysect/core/math/function/float/function1d/tests/test_autowrap.py index 37964197..9059fcd4 100644 --- a/raysect/core/math/function/float/function1d/tests/test_autowrap.py +++ b/raysect/core/math/function/float/function1d/tests/test_autowrap.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/tests/test_base.py b/raysect/core/math/function/float/function1d/tests/test_base.py index ead3c2be..9795871a 100644 --- a/raysect/core/math/function/float/function1d/tests/test_base.py +++ b/raysect/core/math/function/float/function1d/tests/test_base.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/tests/test_cmath.py b/raysect/core/math/function/float/function1d/tests/test_cmath.py index b81e24cd..eafe1544 100644 --- a/raysect/core/math/function/float/function1d/tests/test_cmath.py +++ b/raysect/core/math/function/float/function1d/tests/test_cmath.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/tests/test_constant.py b/raysect/core/math/function/float/function1d/tests/test_constant.py index 98eee069..deadd77a 100644 --- a/raysect/core/math/function/float/function1d/tests/test_constant.py +++ b/raysect/core/math/function/float/function1d/tests/test_constant.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/tests/test_interpolator.py b/raysect/core/math/function/float/function1d/tests/test_interpolator.py index 670c35ce..1cd3bce6 100644 --- a/raysect/core/math/function/float/function1d/tests/test_interpolator.py +++ b/raysect/core/math/function/float/function1d/tests/test_interpolator.py @@ -1,5 +1,5 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function1d/tests/test_samplers.py b/raysect/core/math/function/float/function1d/tests/test_samplers.py index c2f88c42..6a237a8c 100644 --- a/raysect/core/math/function/float/function1d/tests/test_samplers.py +++ b/raysect/core/math/function/float/function1d/tests/test_samplers.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/__init__.pxd b/raysect/core/math/function/float/function2d/__init__.pxd index 4f7767f9..e4b5cdac 100644 --- a/raysect/core/math/function/float/function2d/__init__.pxd +++ b/raysect/core/math/function/float/function2d/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/__init__.py b/raysect/core/math/function/float/function2d/__init__.py index 75bce885..4b532aa3 100644 --- a/raysect/core/math/function/float/function2d/__init__.py +++ b/raysect/core/math/function/float/function2d/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/arg.pxd b/raysect/core/math/function/float/function2d/arg.pxd index f2ce866d..401edbe3 100644 --- a/raysect/core/math/function/float/function2d/arg.pxd +++ b/raysect/core/math/function/float/function2d/arg.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/arg.pyx b/raysect/core/math/function/float/function2d/arg.pyx index efd6f490..dc5c76fe 100644 --- a/raysect/core/math/function/float/function2d/arg.pyx +++ b/raysect/core/math/function/float/function2d/arg.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/autowrap.pxd b/raysect/core/math/function/float/function2d/autowrap.pxd index f23991c1..32f1cd3c 100644 --- a/raysect/core/math/function/float/function2d/autowrap.pxd +++ b/raysect/core/math/function/float/function2d/autowrap.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/autowrap.pyx b/raysect/core/math/function/float/function2d/autowrap.pyx index e2d0a9af..e9da15da 100644 --- a/raysect/core/math/function/float/function2d/autowrap.pyx +++ b/raysect/core/math/function/float/function2d/autowrap.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/base.pxd b/raysect/core/math/function/float/function2d/base.pxd index 8cc41121..aed5f8fe 100644 --- a/raysect/core/math/function/float/function2d/base.pxd +++ b/raysect/core/math/function/float/function2d/base.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/base.pyx b/raysect/core/math/function/float/function2d/base.pyx index f8d80567..a689415b 100644 --- a/raysect/core/math/function/float/function2d/base.pyx +++ b/raysect/core/math/function/float/function2d/base.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -63,110 +63,162 @@ cdef class Function2D(FloatFunction): """ return self.evaluate(x, y) - def __add__(object a, object b): - if is_callable(a): - if is_callable(b): - # a() + b() - return AddFunction2D(a, b) - elif isinstance(b, numbers.Real): - # a() + B -> B + a() - return AddScalar2D( b, a) - elif isinstance(a, numbers.Real): - if is_callable(b): - # A + b() - return AddScalar2D( a, b) + def __add__(self, object b): + + if is_callable(b): + # a() + b() + return AddFunction2D(self, b) + + elif isinstance(b, numbers.Real): + # a() + B -> B + a() + return AddScalar2D( b, self) + return NotImplemented - def __sub__(object a, object b): - if is_callable(a): - if is_callable(b): - # a() - b() - return SubtractFunction2D(a, b) - elif isinstance(b, numbers.Real): - # a() - B -> -B + a() - return AddScalar2D(-( b), a) - elif isinstance(a, numbers.Real): - if is_callable(b): - # A - b() - return SubtractScalar2D( a, b) + def __radd__(self, object a): + return self.__add__(a) + + def __sub__(self, object b): + + if is_callable(b): + # a() - b() + return SubtractFunction2D(self, b) + + elif isinstance(b, numbers.Real): + # a() - B -> -B + a() + return AddScalar2D(-( b), self) + return NotImplemented - def __mul__(object a, object b): + def __rsub__(self, object a): + if is_callable(a): - if is_callable(b): - # a() * b() - return MultiplyFunction2D(a, b) - elif isinstance(b, numbers.Real): - # a() * B -> B * a() - return MultiplyScalar2D( b, a) + # a() - b() + return SubtractFunction2D(a, self) + elif isinstance(a, numbers.Real): - if is_callable(b): - # A * b() - return MultiplyScalar2D( a, b) + # A - b() + return SubtractScalar2D( a, self) + return NotImplemented + def __mul__(self, object b): + + if is_callable(b): + # a() * b() + return MultiplyFunction2D(self, b) + + elif isinstance(b, numbers.Real): + # a() * B -> B * a() + return MultiplyScalar2D( b, self) + + return NotImplemented + + def __rmul__(self, object a): + return self.__mul__(a) + @cython.cdivision(True) - def __truediv__(object a, object b): + def __truediv__(self, object b): + cdef double v + + if is_callable(b): + # a() / b() + return DivideFunction2D(self, b) + + elif isinstance(b, numbers.Real): + # a() / B -> 1/B * a() + v = b + if v == 0.0: + raise ZeroDivisionError("Scalar used as the denominator of the division is zero valued.") + return MultiplyScalar2D(1/v, self) + + return NotImplemented + + @cython.cdivision(True) + def __rtruediv__(self, object a): + if is_callable(a): - if is_callable(b): - # a() / b() - return DivideFunction2D(a, b) - elif isinstance(b, numbers.Real): - # a() / B -> 1/B * a() - v = b - if v == 0.0: - raise ZeroDivisionError("Scalar used as the denominator of the division is zero valued.") - return MultiplyScalar2D(1/v, a) + # a() / b() + return DivideFunction2D(a, self) + elif isinstance(a, numbers.Real): - if is_callable(b): - # A * b() - return DivideScalar2D( a, b) + # A / b() + return DivideScalar2D( a, self) + return NotImplemented - def __mod__(object a, object b): + def __mod__(self, object b): + cdef double v + + if is_callable(b): + # a() % b() + return ModuloFunction2D(self, b) + + elif isinstance(b, numbers.Real): + # a() % B + v = b + if v == 0.0: + raise ZeroDivisionError("Scalar used as the divisor of the division is zero valued.") + return ModuloFunctionScalar2D(self, v) + + return NotImplemented + + def __rmod__(self, object a): + if is_callable(a): - if is_callable(b): - # a() % b() - return ModuloFunction2D(a, b) - elif isinstance(b, numbers.Real): - # a() % B - v = b - if v == 0.0: - raise ZeroDivisionError("Scalar used as the divisor of the division is zero valued.") - return ModuloFunctionScalar2D(a, v) + # a() % b() + return ModuloFunction2D(a, self) + elif isinstance(a, numbers.Real): - if is_callable(b): - # A % b() - return ModuloScalarFunction2D( a, b) + # A % b() + return ModuloScalarFunction2D( a, self) + return NotImplemented def __neg__(self): return MultiplyScalar2D(-1, self) - def __pow__(object a, object b, object c): + def __pow__(self, object b, object c): + if c is not None: # Optimised implementation of pow(a, b, c) not available: fall back # to general implementation - return (a ** b) % c + return PowFunction2D(self, b) % c + + if is_callable(b): + # a() ** b() + return PowFunction2D(self, b) + + elif isinstance(b, numbers.Real): + # a() ** b + return PowFunctionScalar2D(self, b) + + return NotImplemented + + def __rpow__(self, object a, object c): + + if c is not None: + # Optimised implementation of pow(a, b, c) not available: fall back + # to general implementation + return PowFunction2D(a, self) % c + if is_callable(a): - if is_callable(b): - # a() ** b() - return PowFunction2D(a, b) - elif isinstance(b, numbers.Real): - # a() ** b - return PowFunctionScalar2D(a, b) + # a() ** b() + return PowFunction2D(a, self) + elif isinstance(a, numbers.Real): - if is_callable(b): - # a ** b() - return PowScalarFunction2D( a, b) + # A ** b() + return PowScalarFunction2D( a, self) + return NotImplemented def __abs__(self): return AbsFunction2D(self) def __richcmp__(self, object other, int op): + if is_callable(other): if op == Py_EQ: return EqualsFunction2D(self, other) @@ -180,6 +232,7 @@ cdef class Function2D(FloatFunction): return LessEqualsFunction2D(self, other) if op == Py_GE: return GreaterEqualsFunction2D(self, other) + if isinstance(other, numbers.Real): if op == Py_EQ: return EqualsScalar2D( other, self) @@ -197,6 +250,7 @@ cdef class Function2D(FloatFunction): if op == Py_GE: # f() >= K -> K <= f return LessEqualsScalar2D( other, self) + return NotImplemented diff --git a/raysect/core/math/function/float/function2d/blend.pxd b/raysect/core/math/function/float/function2d/blend.pxd index 2bb1cd40..010d628b 100644 --- a/raysect/core/math/function/float/function2d/blend.pxd +++ b/raysect/core/math/function/float/function2d/blend.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/blend.pyx b/raysect/core/math/function/float/function2d/blend.pyx index 570738b2..e7c31992 100644 --- a/raysect/core/math/function/float/function2d/blend.pyx +++ b/raysect/core/math/function/float/function2d/blend.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/cmath.pxd b/raysect/core/math/function/float/function2d/cmath.pxd index 1a8de05e..aad5ae48 100644 --- a/raysect/core/math/function/float/function2d/cmath.pxd +++ b/raysect/core/math/function/float/function2d/cmath.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/cmath.pyx b/raysect/core/math/function/float/function2d/cmath.pyx index ba93ef36..80ba6716 100644 --- a/raysect/core/math/function/float/function2d/cmath.pyx +++ b/raysect/core/math/function/float/function2d/cmath.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/constant.pxd b/raysect/core/math/function/float/function2d/constant.pxd index 45714c48..e56437e1 100644 --- a/raysect/core/math/function/float/function2d/constant.pxd +++ b/raysect/core/math/function/float/function2d/constant.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/constant.pyx b/raysect/core/math/function/float/function2d/constant.pyx index c95accc7..320b55a7 100644 --- a/raysect/core/math/function/float/function2d/constant.pyx +++ b/raysect/core/math/function/float/function2d/constant.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/interpolate/__init__.pxd b/raysect/core/math/function/float/function2d/interpolate/__init__.pxd index edca0a8a..05130a1d 100644 --- a/raysect/core/math/function/float/function2d/interpolate/__init__.pxd +++ b/raysect/core/math/function/float/function2d/interpolate/__init__.pxd @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/interpolate/__init__.py b/raysect/core/math/function/float/function2d/interpolate/__init__.py index bbf8b55f..59c50e45 100644 --- a/raysect/core/math/function/float/function2d/interpolate/__init__.py +++ b/raysect/core/math/function/float/function2d/interpolate/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/interpolate/common.pxd b/raysect/core/math/function/float/function2d/interpolate/common.pxd index febecc1d..700cd1d8 100644 --- a/raysect/core/math/function/float/function2d/interpolate/common.pxd +++ b/raysect/core/math/function/float/function2d/interpolate/common.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/interpolate/common.pyx b/raysect/core/math/function/float/function2d/interpolate/common.pyx index ddfb68f7..58fb27e0 100644 --- a/raysect/core/math/function/float/function2d/interpolate/common.pyx +++ b/raysect/core/math/function/float/function2d/interpolate/common.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -38,15 +38,16 @@ from raysect.core.math.cython cimport barycentric_inside_triangle, barycentric_c cimport cython # bounding box is padded by a small amount to avoid numerical accuracy issues -DEF BOX_PADDING = 1e-6 +cdef const double BOX_PADDING = 1e-6 # convenience defines -DEF V1 = 0 -DEF V2 = 1 -DEF V3 = 2 +cdef enum: + V1 = 0 + V2 = 1 + V3 = 2 -DEF X = 0 -DEF Y = 1 + X = 0 + Y = 1 cdef class MeshKDTree2D(KDTree2DCore): diff --git a/raysect/core/math/function/float/function2d/interpolate/discrete2dmesh.pxd b/raysect/core/math/function/float/function2d/interpolate/discrete2dmesh.pxd index 88197139..8fa578cb 100644 --- a/raysect/core/math/function/float/function2d/interpolate/discrete2dmesh.pxd +++ b/raysect/core/math/function/float/function2d/interpolate/discrete2dmesh.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/interpolate/discrete2dmesh.pyx b/raysect/core/math/function/float/function2d/interpolate/discrete2dmesh.pyx index 6acb320b..e7494cf8 100644 --- a/raysect/core/math/function/float/function2d/interpolate/discrete2dmesh.pyx +++ b/raysect/core/math/function/float/function2d/interpolate/discrete2dmesh.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/interpolate/interpolator2darray.pxd b/raysect/core/math/function/float/function2d/interpolate/interpolator2darray.pxd index 742becbc..0f9d3978 100644 --- a/raysect/core/math/function/float/function2d/interpolate/interpolator2darray.pxd +++ b/raysect/core/math/function/float/function2d/interpolate/interpolator2darray.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/interpolate/interpolator2darray.pyx b/raysect/core/math/function/float/function2d/interpolate/interpolator2darray.pyx index 988021f3..0afca494 100644 --- a/raysect/core/math/function/float/function2d/interpolate/interpolator2darray.pyx +++ b/raysect/core/math/function/float/function2d/interpolate/interpolator2darray.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/interpolate/interpolator2dmesh.pxd b/raysect/core/math/function/float/function2d/interpolate/interpolator2dmesh.pxd index d97f3446..8794c150 100644 --- a/raysect/core/math/function/float/function2d/interpolate/interpolator2dmesh.pxd +++ b/raysect/core/math/function/float/function2d/interpolate/interpolator2dmesh.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/interpolate/interpolator2dmesh.pyx b/raysect/core/math/function/float/function2d/interpolate/interpolator2dmesh.pyx index 2bbca3d7..62ddde44 100644 --- a/raysect/core/math/function/float/function2d/interpolate/interpolator2dmesh.pyx +++ b/raysect/core/math/function/float/function2d/interpolate/interpolator2dmesh.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/interpolate/meson.build b/raysect/core/math/function/float/function2d/interpolate/meson.build new file mode 100644 index 00000000..80c28a76 --- /dev/null +++ b/raysect/core/math/function/float/function2d/interpolate/meson.build @@ -0,0 +1,30 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/float/function2d/interpolate' + +# source files +py_files = ['__init__.py'] +pyx_files = ['common.pyx', 'discrete2dmesh.pyx', 'interpolator2darray.pyx', 'interpolator2dmesh.pyx'] +pxd_files = ['__init__.pxd', 'common.pxd', 'discrete2dmesh.pxd', 'interpolator2darray.pxd', 'interpolator2dmesh.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('tests') diff --git a/raysect/core/math/function/float/function2d/interpolate/tests/data/meson.build b/raysect/core/math/function/float/function2d/interpolate/tests/data/meson.build new file mode 100644 index 00000000..c2c7b3c2 --- /dev/null +++ b/raysect/core/math/function/float/function2d/interpolate/tests/data/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/float/function2d/interpolate/tests/data' + +# source files +py_files = ['interpolator2d_test_data.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/core/math/function/float/function2d/interpolate/tests/meson.build b/raysect/core/math/function/float/function2d/interpolate/tests/meson.build new file mode 100644 index 00000000..75b34a0c --- /dev/null +++ b/raysect/core/math/function/float/function2d/interpolate/tests/meson.build @@ -0,0 +1,30 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/float/function2d/interpolate/tests' + +# source files +py_files = ['__init__.py', 'test_interpolator_2d.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('data') diff --git a/raysect/core/math/function/float/function2d/interpolate/tests/scripts/.meson-exclude b/raysect/core/math/function/float/function2d/interpolate/tests/scripts/.meson-exclude new file mode 100644 index 00000000..e69de29b diff --git a/raysect/core/math/function/float/function2d/interpolate/tests/scripts/generate_2d_splines.py b/raysect/core/math/function/float/function2d/interpolate/tests/scripts/generate_2d_splines.py index 8847beab..998a7292 100644 --- a/raysect/core/math/function/float/function2d/interpolate/tests/scripts/generate_2d_splines.py +++ b/raysect/core/math/function/float/function2d/interpolate/tests/scripts/generate_2d_splines.py @@ -1,5 +1,5 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/interpolate/tests/test_interpolator_2d.py b/raysect/core/math/function/float/function2d/interpolate/tests/test_interpolator_2d.py index e538d237..1ed9e602 100644 --- a/raysect/core/math/function/float/function2d/interpolate/tests/test_interpolator_2d.py +++ b/raysect/core/math/function/float/function2d/interpolate/tests/test_interpolator_2d.py @@ -1,5 +1,5 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/meson.build b/raysect/core/math/function/float/function2d/meson.build new file mode 100644 index 00000000..60016468 --- /dev/null +++ b/raysect/core/math/function/float/function2d/meson.build @@ -0,0 +1,31 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/float/function2d' + +# source files +py_files = ['__init__.py'] +pyx_files = ['arg.pyx', 'autowrap.pyx', 'base.pyx', 'blend.pyx', 'cmath.pyx', 'constant.pyx'] +pxd_files = ['__init__.pxd', 'arg.pxd', 'autowrap.pxd', 'base.pxd', 'blend.pxd', 'cmath.pxd', 'constant.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('interpolate') +subdir('tests') diff --git a/raysect/core/math/function/float/function2d/tests/meson.build b/raysect/core/math/function/float/function2d/tests/meson.build new file mode 100644 index 00000000..44b5ea1a --- /dev/null +++ b/raysect/core/math/function/float/function2d/tests/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/float/function2d/tests' + +# source files +py_files = ['__init__.py', 'test_arg.py', 'test_autowrap.py', 'test_base.py', 'test_cmath.py', 'test_constant.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/core/math/function/float/function2d/tests/test_arg.py b/raysect/core/math/function/float/function2d/tests/test_arg.py index 378713f5..4d588e09 100644 --- a/raysect/core/math/function/float/function2d/tests/test_arg.py +++ b/raysect/core/math/function/float/function2d/tests/test_arg.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/tests/test_autowrap.py b/raysect/core/math/function/float/function2d/tests/test_autowrap.py index a050dfa7..179326bd 100644 --- a/raysect/core/math/function/float/function2d/tests/test_autowrap.py +++ b/raysect/core/math/function/float/function2d/tests/test_autowrap.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/tests/test_base.py b/raysect/core/math/function/float/function2d/tests/test_base.py index 365b3d32..d8acdf78 100644 --- a/raysect/core/math/function/float/function2d/tests/test_base.py +++ b/raysect/core/math/function/float/function2d/tests/test_base.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/tests/test_cmath.py b/raysect/core/math/function/float/function2d/tests/test_cmath.py index 0e838492..eaceaccc 100644 --- a/raysect/core/math/function/float/function2d/tests/test_cmath.py +++ b/raysect/core/math/function/float/function2d/tests/test_cmath.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function2d/tests/test_constant.py b/raysect/core/math/function/float/function2d/tests/test_constant.py index 2cf71b3b..96b081a3 100644 --- a/raysect/core/math/function/float/function2d/tests/test_constant.py +++ b/raysect/core/math/function/float/function2d/tests/test_constant.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/__init__.pxd b/raysect/core/math/function/float/function3d/__init__.pxd index abe63a22..5141e672 100644 --- a/raysect/core/math/function/float/function3d/__init__.pxd +++ b/raysect/core/math/function/float/function3d/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/__init__.py b/raysect/core/math/function/float/function3d/__init__.py index ee926ab7..7998e002 100644 --- a/raysect/core/math/function/float/function3d/__init__.py +++ b/raysect/core/math/function/float/function3d/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/arg.pxd b/raysect/core/math/function/float/function3d/arg.pxd index d5a262a2..3c4aa58b 100644 --- a/raysect/core/math/function/float/function3d/arg.pxd +++ b/raysect/core/math/function/float/function3d/arg.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/arg.pyx b/raysect/core/math/function/float/function3d/arg.pyx index 8672e9fb..c8e276fb 100644 --- a/raysect/core/math/function/float/function3d/arg.pyx +++ b/raysect/core/math/function/float/function3d/arg.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/autowrap.pxd b/raysect/core/math/function/float/function3d/autowrap.pxd index 0f9e4d65..6c09fdc4 100644 --- a/raysect/core/math/function/float/function3d/autowrap.pxd +++ b/raysect/core/math/function/float/function3d/autowrap.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/autowrap.pyx b/raysect/core/math/function/float/function3d/autowrap.pyx index e45459a0..de9b8355 100644 --- a/raysect/core/math/function/float/function3d/autowrap.pyx +++ b/raysect/core/math/function/float/function3d/autowrap.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/base.pxd b/raysect/core/math/function/float/function3d/base.pxd index f9b67a28..679fa29b 100644 --- a/raysect/core/math/function/float/function3d/base.pxd +++ b/raysect/core/math/function/float/function3d/base.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/base.pyx b/raysect/core/math/function/float/function3d/base.pyx index b5f1933f..f5cdf065 100644 --- a/raysect/core/math/function/float/function3d/base.pyx +++ b/raysect/core/math/function/float/function3d/base.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -64,110 +64,162 @@ cdef class Function3D(FloatFunction): """ return self.evaluate(x, y, z) - def __add__(object a, object b): - if is_callable(a): - if is_callable(b): - # a() + b() - return AddFunction3D(a, b) - elif isinstance(b, numbers.Real): - # a() + B -> B + a() - return AddScalar3D( b, a) - elif isinstance(a, numbers.Real): - if is_callable(b): - # A + b() - return AddScalar3D( a, b) + def __add__(self, object b): + + if is_callable(b): + # a() + b() + return AddFunction3D(self, b) + + elif isinstance(b, numbers.Real): + # a() + B -> B + a() + return AddScalar3D( b, self) + return NotImplemented - def __sub__(object a, object b): - if is_callable(a): - if is_callable(b): - # a() - b() - return SubtractFunction3D(a, b) - elif isinstance(b, numbers.Real): - # a() - B -> -B + a() - return AddScalar3D(-( b), a) - elif isinstance(a, numbers.Real): - if is_callable(b): - # A - b() - return SubtractScalar3D( a, b) + def __radd__(self, object a): + return self.__add__(a) + + def __sub__(self, object b): + + if is_callable(b): + # a() - b() + return SubtractFunction3D(self, b) + + elif isinstance(b, numbers.Real): + # a() - B -> -B + a() + return AddScalar3D(-( b), self) + return NotImplemented + + def __rsub__(self, object a): - def __mul__(object a, object b): if is_callable(a): - if is_callable(b): - # a() * b() - return MultiplyFunction3D(a, b) - elif isinstance(b, numbers.Real): - # a() * B -> B * a() - return MultiplyScalar3D( b, a) + # a() - b() + return SubtractFunction3D(a, self) + elif isinstance(a, numbers.Real): - if is_callable(b): - # A * b() - return MultiplyScalar3D( a, b) + # A - b() + return SubtractScalar3D( a, self) + return NotImplemented + def __mul__(self, object b): + + if is_callable(b): + # a() * b() + return MultiplyFunction3D(self, b) + + elif isinstance(b, numbers.Real): + # a() * B -> B * a() + return MultiplyScalar3D( b, self) + + return NotImplemented + + def __rmul__(self, object a): + return self.__mul__(a) + @cython.cdivision(True) - def __truediv__(object a, object b): + def __truediv__(self, object b): + cdef double v + + if is_callable(b): + # a() / b() + return DivideFunction3D(self, b) + + elif isinstance(b, numbers.Real): + # a() / B -> 1/B * a() + v = b + if v == 0.0: + raise ZeroDivisionError("Scalar used as the denominator of the division is zero valued.") + return MultiplyScalar3D(1/v, self) + + return NotImplemented + + @cython.cdivision(True) + def __rtruediv__(self, object a): + if is_callable(a): - if is_callable(b): - # a() / b() - return DivideFunction3D(a, b) - elif isinstance(b, numbers.Real): - # a() / B -> 1/B * a() - v = b - if v == 0.0: - raise ZeroDivisionError("Scalar used as the denominator of the division is zero valued.") - return MultiplyScalar3D(1/v, a) + # a() / b() + return DivideFunction3D(a, self) + elif isinstance(a, numbers.Real): - if is_callable(b): - # A * b() - return DivideScalar3D( a, b) + # A / b() + return DivideScalar3D( a, self) + return NotImplemented - def __mod__(object a, object b): + def __mod__(self, object b): + cdef double v + + if is_callable(b): + # a() % b() + return ModuloFunction3D(self, b) + + elif isinstance(b, numbers.Real): + # a() % B + v = b + if v == 0.0: + raise ZeroDivisionError("Scalar used as the divisor of the division is zero valued.") + return ModuloFunctionScalar3D(self, v) + + return NotImplemented + + def __rmod__(self, object a): + if is_callable(a): - if is_callable(b): - # a() % b() - return ModuloFunction3D(a, b) - elif isinstance(b, numbers.Real): - # a() % B - v = b - if v == 0.0: - raise ZeroDivisionError("Scalar used as the divisor of the division is zero valued.") - return ModuloFunctionScalar3D(a, v) + # a() % b() + return ModuloFunction3D(a, self) + elif isinstance(a, numbers.Real): - if is_callable(b): - # A % b() - return ModuloScalarFunction3D( a, b) + # A % b() + return ModuloScalarFunction3D( a, self) + return NotImplemented def __neg__(self): return MultiplyScalar3D(-1, self) - def __pow__(object a, object b, object c): + def __pow__(self, object b, object c): + if c is not None: # Optimised implementation of pow(a, b, c) not available: fall back # to general implementation - return (a ** b) % c + return PowFunction3D(self, b) % c + + if is_callable(b): + # a() ** b() + return PowFunction3D(self, b) + + elif isinstance(b, numbers.Real): + # a() ** b + return PowFunctionScalar3D(self, b) + + return NotImplemented + + def __rpow__(self, object a, object c): + + if c is not None: + # Optimised implementation of pow(a, b, c) not available: fall back + # to general implementation + return PowFunction3D(a, self) % c + if is_callable(a): - if is_callable(b): - # a() ** b() - return PowFunction3D(a, b) - elif isinstance(b, numbers.Real): - # a() ** b - return PowFunctionScalar3D(a, b) + # a() ** b() + return PowFunction3D(a, self) + elif isinstance(a, numbers.Real): - if is_callable(b): - # a ** b() - return PowScalarFunction3D( a, b) + # A ** b() + return PowScalarFunction3D( a, self) + return NotImplemented def __abs__(self): return AbsFunction3D(self) def __richcmp__(self, object other, int op): + if is_callable(other): if op == Py_EQ: return EqualsFunction3D(self, other) @@ -181,6 +233,7 @@ cdef class Function3D(FloatFunction): return LessEqualsFunction3D(self, other) if op == Py_GE: return GreaterEqualsFunction3D(self, other) + if isinstance(other, numbers.Real): if op == Py_EQ: return EqualsScalar3D( other, self) @@ -198,6 +251,7 @@ cdef class Function3D(FloatFunction): if op == Py_GE: # f() >= K -> K <= f return LessEqualsScalar3D( other, self) + return NotImplemented diff --git a/raysect/core/math/function/float/function3d/blend.pxd b/raysect/core/math/function/float/function3d/blend.pxd index f1dc75e7..3cf06ffe 100644 --- a/raysect/core/math/function/float/function3d/blend.pxd +++ b/raysect/core/math/function/float/function3d/blend.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/blend.pyx b/raysect/core/math/function/float/function3d/blend.pyx index 75672a99..79c54359 100644 --- a/raysect/core/math/function/float/function3d/blend.pyx +++ b/raysect/core/math/function/float/function3d/blend.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/cmath.pxd b/raysect/core/math/function/float/function3d/cmath.pxd index da2b9584..af95f92d 100644 --- a/raysect/core/math/function/float/function3d/cmath.pxd +++ b/raysect/core/math/function/float/function3d/cmath.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/cmath.pyx b/raysect/core/math/function/float/function3d/cmath.pyx index 95cea1ef..f6c9de2d 100644 --- a/raysect/core/math/function/float/function3d/cmath.pyx +++ b/raysect/core/math/function/float/function3d/cmath.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/constant.pxd b/raysect/core/math/function/float/function3d/constant.pxd index 0d3d0ae8..30d38ba0 100644 --- a/raysect/core/math/function/float/function3d/constant.pxd +++ b/raysect/core/math/function/float/function3d/constant.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/constant.pyx b/raysect/core/math/function/float/function3d/constant.pyx index 7a21b9ba..00642ebc 100644 --- a/raysect/core/math/function/float/function3d/constant.pyx +++ b/raysect/core/math/function/float/function3d/constant.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/interpolate/__init__.pxd b/raysect/core/math/function/float/function3d/interpolate/__init__.pxd index 3e110c28..72614b33 100644 --- a/raysect/core/math/function/float/function3d/interpolate/__init__.pxd +++ b/raysect/core/math/function/float/function3d/interpolate/__init__.pxd @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/interpolate/__init__.py b/raysect/core/math/function/float/function3d/interpolate/__init__.py index 97efcda4..d4a3cd75 100644 --- a/raysect/core/math/function/float/function3d/interpolate/__init__.py +++ b/raysect/core/math/function/float/function3d/interpolate/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/interpolate/common.pxd b/raysect/core/math/function/float/function3d/interpolate/common.pxd index 2368425a..45c3e385 100644 --- a/raysect/core/math/function/float/function3d/interpolate/common.pxd +++ b/raysect/core/math/function/float/function3d/interpolate/common.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/interpolate/common.pyx b/raysect/core/math/function/float/function3d/interpolate/common.pyx index dee3cc4e..4fa0cdf0 100644 --- a/raysect/core/math/function/float/function3d/interpolate/common.pyx +++ b/raysect/core/math/function/float/function3d/interpolate/common.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -38,17 +38,18 @@ from raysect.core.math.cython cimport barycentric_inside_tetrahedra, barycentric cimport cython # bounding box is padded by a small amount to avoid numerical accuracy issues -DEF BOX_PADDING = 1e-6 +cdef const double BOX_PADDING = 1e-6 # convenience defines -DEF V1 = 0 -DEF V2 = 1 -DEF V3 = 2 -DEF V4 = 3 - -DEF X = 0 -DEF Y = 1 -DEF Z = 2 +cdef enum: + V1 = 0 + V2 = 1 + V3 = 2 + V4 = 3 + + X = 0 + Y = 1 + Z = 2 cdef class MeshKDTree3D(KDTree3DCore): diff --git a/raysect/core/math/function/float/function3d/interpolate/discrete3dmesh.pxd b/raysect/core/math/function/float/function3d/interpolate/discrete3dmesh.pxd index 71c07c5c..d3eb7a77 100644 --- a/raysect/core/math/function/float/function3d/interpolate/discrete3dmesh.pxd +++ b/raysect/core/math/function/float/function3d/interpolate/discrete3dmesh.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/interpolate/discrete3dmesh.pyx b/raysect/core/math/function/float/function3d/interpolate/discrete3dmesh.pyx index 79388df2..a61bb236 100644 --- a/raysect/core/math/function/float/function3d/interpolate/discrete3dmesh.pyx +++ b/raysect/core/math/function/float/function3d/interpolate/discrete3dmesh.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/interpolate/interpolator3darray.pxd b/raysect/core/math/function/float/function3d/interpolate/interpolator3darray.pxd index 5b0a17d5..d5ef41ff 100644 --- a/raysect/core/math/function/float/function3d/interpolate/interpolator3darray.pxd +++ b/raysect/core/math/function/float/function3d/interpolate/interpolator3darray.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/interpolate/interpolator3darray.pyx b/raysect/core/math/function/float/function3d/interpolate/interpolator3darray.pyx index 6aa9488b..7c93ea85 100644 --- a/raysect/core/math/function/float/function3d/interpolate/interpolator3darray.pyx +++ b/raysect/core/math/function/float/function3d/interpolate/interpolator3darray.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/interpolate/meson.build b/raysect/core/math/function/float/function3d/interpolate/meson.build new file mode 100644 index 00000000..7d4c2c6b --- /dev/null +++ b/raysect/core/math/function/float/function3d/interpolate/meson.build @@ -0,0 +1,30 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/float/function3d/interpolate' + +# source files +py_files = ['__init__.py'] +pyx_files = ['common.pyx', 'discrete3dmesh.pyx', 'interpolator3darray.pyx'] +pxd_files = ['__init__.pxd', 'common.pxd', 'discrete3dmesh.pxd', 'interpolator3darray.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('tests') diff --git a/raysect/core/math/function/float/function3d/interpolate/tests/data/meson.build b/raysect/core/math/function/float/function3d/interpolate/tests/data/meson.build new file mode 100644 index 00000000..430429d5 --- /dev/null +++ b/raysect/core/math/function/float/function3d/interpolate/tests/data/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/float/function3d/interpolate/tests/data' + +# source files +py_files = ['interpolator3d_test_data.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/core/math/function/float/function3d/interpolate/tests/meson.build b/raysect/core/math/function/float/function3d/interpolate/tests/meson.build new file mode 100644 index 00000000..66468dc2 --- /dev/null +++ b/raysect/core/math/function/float/function3d/interpolate/tests/meson.build @@ -0,0 +1,30 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/float/function3d/interpolate/tests' + +# source files +py_files = ['__init__.py', 'test_interpolator_3d.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('data') diff --git a/raysect/core/math/function/float/function3d/interpolate/tests/scripts/.meson-exclude b/raysect/core/math/function/float/function3d/interpolate/tests/scripts/.meson-exclude new file mode 100644 index 00000000..e69de29b diff --git a/raysect/core/math/function/float/function3d/interpolate/tests/scripts/generate_3d_splines.py b/raysect/core/math/function/float/function3d/interpolate/tests/scripts/generate_3d_splines.py index 4df2faeb..d1e52a3e 100644 --- a/raysect/core/math/function/float/function3d/interpolate/tests/scripts/generate_3d_splines.py +++ b/raysect/core/math/function/float/function3d/interpolate/tests/scripts/generate_3d_splines.py @@ -1,5 +1,5 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/interpolate/tests/test_interpolator_3d.py b/raysect/core/math/function/float/function3d/interpolate/tests/test_interpolator_3d.py index 33ba56bb..4c6cd5d9 100644 --- a/raysect/core/math/function/float/function3d/interpolate/tests/test_interpolator_3d.py +++ b/raysect/core/math/function/float/function3d/interpolate/tests/test_interpolator_3d.py @@ -1,5 +1,5 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/meson.build b/raysect/core/math/function/float/function3d/meson.build new file mode 100644 index 00000000..0f1d48f5 --- /dev/null +++ b/raysect/core/math/function/float/function3d/meson.build @@ -0,0 +1,31 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/float/function3d' + +# source files +py_files = ['__init__.py'] +pyx_files = ['arg.pyx', 'autowrap.pyx', 'base.pyx', 'blend.pyx', 'cmath.pyx', 'constant.pyx'] +pxd_files = ['__init__.pxd', 'arg.pxd', 'autowrap.pxd', 'base.pxd', 'blend.pxd', 'cmath.pxd', 'constant.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('interpolate') +subdir('tests') diff --git a/raysect/core/math/function/float/function3d/tests/meson.build b/raysect/core/math/function/float/function3d/tests/meson.build new file mode 100644 index 00000000..ce4b4c74 --- /dev/null +++ b/raysect/core/math/function/float/function3d/tests/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/float/function3d/tests' + +# source files +py_files = ['__init__.py', 'test_arg.py', 'test_autowrap.py', 'test_base.py', 'test_cmath.py', 'test_constant.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/core/math/function/float/function3d/tests/test_arg.py b/raysect/core/math/function/float/function3d/tests/test_arg.py index 0019c1db..24babb6d 100644 --- a/raysect/core/math/function/float/function3d/tests/test_arg.py +++ b/raysect/core/math/function/float/function3d/tests/test_arg.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/tests/test_autowrap.py b/raysect/core/math/function/float/function3d/tests/test_autowrap.py index e96eeba6..32f24bac 100644 --- a/raysect/core/math/function/float/function3d/tests/test_autowrap.py +++ b/raysect/core/math/function/float/function3d/tests/test_autowrap.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/tests/test_base.py b/raysect/core/math/function/float/function3d/tests/test_base.py index fc5f622c..8984f19f 100644 --- a/raysect/core/math/function/float/function3d/tests/test_base.py +++ b/raysect/core/math/function/float/function3d/tests/test_base.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/tests/test_cmath.py b/raysect/core/math/function/float/function3d/tests/test_cmath.py index cd02bfaa..9a3fbede 100644 --- a/raysect/core/math/function/float/function3d/tests/test_cmath.py +++ b/raysect/core/math/function/float/function3d/tests/test_cmath.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/function3d/tests/test_constant.py b/raysect/core/math/function/float/function3d/tests/test_constant.py index 22b632c1..ff6d1e57 100644 --- a/raysect/core/math/function/float/function3d/tests/test_constant.py +++ b/raysect/core/math/function/float/function3d/tests/test_constant.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/float/meson.build b/raysect/core/math/function/float/meson.build new file mode 100644 index 00000000..481844b1 --- /dev/null +++ b/raysect/core/math/function/float/meson.build @@ -0,0 +1,32 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/float' + +# source files +py_files = ['__init__.py'] +pyx_files = ['base.pyx'] +pxd_files = ['__init__.pxd', 'base.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('function1d') +subdir('function2d') +subdir('function3d') diff --git a/raysect/core/math/function/meson.build b/raysect/core/math/function/meson.build new file mode 100644 index 00000000..52344203 --- /dev/null +++ b/raysect/core/math/function/meson.build @@ -0,0 +1,31 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function' + +# source files +py_files = ['__init__.py'] +pyx_files = ['base.pyx'] +pxd_files = ['__init__.pxd', 'base.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('float') +subdir('vector3d') diff --git a/raysect/core/math/function/vector3d/__init__.pxd b/raysect/core/math/function/vector3d/__init__.pxd index 0b0af398..7d369007 100644 --- a/raysect/core/math/function/vector3d/__init__.pxd +++ b/raysect/core/math/function/vector3d/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/__init__.py b/raysect/core/math/function/vector3d/__init__.py index a034c18f..3342550d 100644 --- a/raysect/core/math/function/vector3d/__init__.py +++ b/raysect/core/math/function/vector3d/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/base.pxd b/raysect/core/math/function/vector3d/base.pxd index 24ea7cab..1db0cba7 100644 --- a/raysect/core/math/function/vector3d/base.pxd +++ b/raysect/core/math/function/vector3d/base.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/base.pyx b/raysect/core/math/function/vector3d/base.pyx index ba2d1afe..4d97b1b1 100644 --- a/raysect/core/math/function/vector3d/base.pyx +++ b/raysect/core/math/function/vector3d/base.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function1d/__init__.pxd b/raysect/core/math/function/vector3d/function1d/__init__.pxd index 3ea8b908..7e421dd1 100644 --- a/raysect/core/math/function/vector3d/function1d/__init__.pxd +++ b/raysect/core/math/function/vector3d/function1d/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function1d/autowrap.pxd b/raysect/core/math/function/vector3d/function1d/autowrap.pxd index f8a85b72..a41f9d41 100644 --- a/raysect/core/math/function/vector3d/function1d/autowrap.pxd +++ b/raysect/core/math/function/vector3d/function1d/autowrap.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function1d/autowrap.pyx b/raysect/core/math/function/vector3d/function1d/autowrap.pyx index 6ac407b6..679e0193 100644 --- a/raysect/core/math/function/vector3d/function1d/autowrap.pyx +++ b/raysect/core/math/function/vector3d/function1d/autowrap.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function1d/base.pxd b/raysect/core/math/function/vector3d/function1d/base.pxd index 39e8cdb1..1e868efd 100644 --- a/raysect/core/math/function/vector3d/function1d/base.pxd +++ b/raysect/core/math/function/vector3d/function1d/base.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function1d/base.pyx b/raysect/core/math/function/vector3d/function1d/base.pyx index 2cc9942b..5b920431 100644 --- a/raysect/core/math/function/vector3d/function1d/base.pyx +++ b/raysect/core/math/function/vector3d/function1d/base.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -65,31 +65,34 @@ cdef class Function1D(Vector3DFunction): """ return self.evaluate(x) - def __add__(object a, object b): - if is_callable(a) or isinstance(a, Vector3D): - if is_callable(b) or isinstance(b, Vector3D): - return AddFunction1D(a, b) + def __add__(self, object b): + if is_callable(b) or isinstance(b, Vector3D): + return AddFunction1D(self, b) return NotImplemented + + def __radd__(self, object a): + return self.__add__(a) - def __sub__(object a, object b): - if is_callable(a) or isinstance(a, Vector3D): - if is_callable(b) or isinstance(b, Vector3D): - return SubtractFunction1D(a, b) + def __sub__(self, object b): + if is_callable(b) or isinstance(b, Vector3D): + return SubtractFunction1D(self, b) return NotImplemented - - def __mul__(object a, object b): + + def __rsub__(self, object a): if is_callable(a) or isinstance(a, Vector3D): - if float_is_callable(b) or isinstance(b, numbers.Real): - return MultiplyFunction1D(a, b) - if is_callable(b) or isinstance(b, Vector3D): - if float_is_callable(a) or isinstance(a, numbers.Real): - return MultiplyFunction1D(b, a) + return SubtractFunction1D(a, self) + + def __mul__(self, object b): + if float_is_callable(b) or isinstance(b, numbers.Real): + return MultiplyFunction1D(self, b) return NotImplemented + + def __rmul__(self, object a): + return self.__mul__(a) - def __truediv__(object a, object b): - if is_callable(a) or isinstance(a, Vector3D): - if float_is_callable(b) or isinstance(b, numbers.Real): - return DivideFunction1D(a, b) + def __truediv__(self, object b): + if float_is_callable(b) or isinstance(b, numbers.Real): + return DivideFunction1D(self, b) return NotImplemented def __neg__(self): diff --git a/raysect/core/math/function/vector3d/function1d/blend.pxd b/raysect/core/math/function/vector3d/function1d/blend.pxd index 6a68ffca..c1bc5472 100644 --- a/raysect/core/math/function/vector3d/function1d/blend.pxd +++ b/raysect/core/math/function/vector3d/function1d/blend.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function1d/blend.pyx b/raysect/core/math/function/vector3d/function1d/blend.pyx index 1a83d61b..91645a65 100644 --- a/raysect/core/math/function/vector3d/function1d/blend.pyx +++ b/raysect/core/math/function/vector3d/function1d/blend.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function1d/constant.pxd b/raysect/core/math/function/vector3d/function1d/constant.pxd index 297a71ab..d5976d5c 100644 --- a/raysect/core/math/function/vector3d/function1d/constant.pxd +++ b/raysect/core/math/function/vector3d/function1d/constant.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function1d/constant.pyx b/raysect/core/math/function/vector3d/function1d/constant.pyx index bc8423dc..4f59b0ef 100644 --- a/raysect/core/math/function/vector3d/function1d/constant.pyx +++ b/raysect/core/math/function/vector3d/function1d/constant.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function1d/meson.build b/raysect/core/math/function/vector3d/function1d/meson.build new file mode 100644 index 00000000..cad4de14 --- /dev/null +++ b/raysect/core/math/function/vector3d/function1d/meson.build @@ -0,0 +1,30 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/vector3d/function1d' + +# source files +py_files = ['__init__.py'] +pyx_files = ['autowrap.pyx', 'base.pyx', 'blend.pyx', 'constant.pyx', 'utility.pyx'] +pxd_files = ['__init__.pxd', 'autowrap.pxd', 'base.pxd', 'blend.pxd', 'constant.pxd', 'utility.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('tests') diff --git a/raysect/core/math/function/vector3d/function1d/tests/meson.build b/raysect/core/math/function/vector3d/function1d/tests/meson.build new file mode 100644 index 00000000..52dd0712 --- /dev/null +++ b/raysect/core/math/function/vector3d/function1d/tests/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/vector3d/function1d/tests' + +# source files +py_files = ['__init__.py', 'test_autowrap.py', 'test_base.py', 'test_constant.py', 'test_float_to_vector3d.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/core/math/function/vector3d/function1d/tests/test_autowrap.py b/raysect/core/math/function/vector3d/function1d/tests/test_autowrap.py index 296df2ef..6c0391cd 100644 --- a/raysect/core/math/function/vector3d/function1d/tests/test_autowrap.py +++ b/raysect/core/math/function/vector3d/function1d/tests/test_autowrap.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function1d/tests/test_base.py b/raysect/core/math/function/vector3d/function1d/tests/test_base.py index 6827208b..90ec03d2 100644 --- a/raysect/core/math/function/vector3d/function1d/tests/test_base.py +++ b/raysect/core/math/function/vector3d/function1d/tests/test_base.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function1d/tests/test_constant.py b/raysect/core/math/function/vector3d/function1d/tests/test_constant.py index b79a9907..8b34fb7e 100644 --- a/raysect/core/math/function/vector3d/function1d/tests/test_constant.py +++ b/raysect/core/math/function/vector3d/function1d/tests/test_constant.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function1d/tests/test_float_to_vector3d.py b/raysect/core/math/function/vector3d/function1d/tests/test_float_to_vector3d.py index c14f288a..46464486 100644 --- a/raysect/core/math/function/vector3d/function1d/tests/test_float_to_vector3d.py +++ b/raysect/core/math/function/vector3d/function1d/tests/test_float_to_vector3d.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function1d/utility.pxd b/raysect/core/math/function/vector3d/function1d/utility.pxd index a94cf660..de1c1a64 100644 --- a/raysect/core/math/function/vector3d/function1d/utility.pxd +++ b/raysect/core/math/function/vector3d/function1d/utility.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function1d/utility.pyx b/raysect/core/math/function/vector3d/function1d/utility.pyx index 25f64ead..43fe661c 100644 --- a/raysect/core/math/function/vector3d/function1d/utility.pyx +++ b/raysect/core/math/function/vector3d/function1d/utility.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function2d/__init__.pxd b/raysect/core/math/function/vector3d/function2d/__init__.pxd index 18545b5c..8a25facc 100644 --- a/raysect/core/math/function/vector3d/function2d/__init__.pxd +++ b/raysect/core/math/function/vector3d/function2d/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function2d/autowrap.pxd b/raysect/core/math/function/vector3d/function2d/autowrap.pxd index 1bda3174..06c7c52d 100644 --- a/raysect/core/math/function/vector3d/function2d/autowrap.pxd +++ b/raysect/core/math/function/vector3d/function2d/autowrap.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function2d/autowrap.pyx b/raysect/core/math/function/vector3d/function2d/autowrap.pyx index 9c7fb5bb..d6050def 100644 --- a/raysect/core/math/function/vector3d/function2d/autowrap.pyx +++ b/raysect/core/math/function/vector3d/function2d/autowrap.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function2d/base.pxd b/raysect/core/math/function/vector3d/function2d/base.pxd index 78028056..c8159ba9 100644 --- a/raysect/core/math/function/vector3d/function2d/base.pxd +++ b/raysect/core/math/function/vector3d/function2d/base.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function2d/base.pyx b/raysect/core/math/function/vector3d/function2d/base.pyx index 6f3f4ff1..d7856199 100644 --- a/raysect/core/math/function/vector3d/function2d/base.pyx +++ b/raysect/core/math/function/vector3d/function2d/base.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -66,31 +66,34 @@ cdef class Function2D(Vector3DFunction): """ return self.evaluate(x, y) - def __add__(object a, object b): - if is_callable(a) or isinstance(a, Vector3D): - if is_callable(b) or isinstance(b, Vector3D): - return AddFunction2D(a, b) + def __add__(self, object b): + if is_callable(b) or isinstance(b, Vector3D): + return AddFunction2D(self, b) return NotImplemented - def __sub__(object a, object b): - if is_callable(a) or isinstance(a, Vector3D): - if is_callable(b) or isinstance(b, Vector3D): - return SubtractFunction2D(a, b) - return NotImplemented + def __radd__(self, object a): + return self.__add__(a) - def __mul__(object a, object b): - if is_callable(a) or isinstance(a, Vector3D): - if float_is_callable(b) or isinstance(b, numbers.Real): - return MultiplyFunction2D(a, b) + def __sub__(self, object b): if is_callable(b) or isinstance(b, Vector3D): - if float_is_callable(a) or isinstance(a, numbers.Real): - return MultiplyFunction2D(b, a) + return SubtractFunction2D(self, b) return NotImplemented - - def __truediv__(object a, object b): + + def __rsub__(self, object a): if is_callable(a) or isinstance(a, Vector3D): - if float_is_callable(b) or isinstance(b, numbers.Real): - return DivideFunction2D(a, b) + return SubtractFunction2D(a, self) + + def __mul__(self, object b): + if float_is_callable(b) or isinstance(b, numbers.Real): + return MultiplyFunction2D(self, b) + return NotImplemented + + def __rmul__(self, object a): + return self.__mul__(a) + + def __truediv__(self, object b): + if float_is_callable(b) or isinstance(b, numbers.Real): + return DivideFunction2D(self, b) return NotImplemented def __neg__(self): diff --git a/raysect/core/math/function/vector3d/function2d/blend.pxd b/raysect/core/math/function/vector3d/function2d/blend.pxd index 6177e866..dd55f465 100644 --- a/raysect/core/math/function/vector3d/function2d/blend.pxd +++ b/raysect/core/math/function/vector3d/function2d/blend.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function2d/blend.pyx b/raysect/core/math/function/vector3d/function2d/blend.pyx index b808d1a6..6a69c7e7 100644 --- a/raysect/core/math/function/vector3d/function2d/blend.pyx +++ b/raysect/core/math/function/vector3d/function2d/blend.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function2d/constant.pxd b/raysect/core/math/function/vector3d/function2d/constant.pxd index 828c7de0..9b63f5a0 100644 --- a/raysect/core/math/function/vector3d/function2d/constant.pxd +++ b/raysect/core/math/function/vector3d/function2d/constant.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function2d/constant.pyx b/raysect/core/math/function/vector3d/function2d/constant.pyx index ff4f8b47..4656e368 100644 --- a/raysect/core/math/function/vector3d/function2d/constant.pyx +++ b/raysect/core/math/function/vector3d/function2d/constant.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function2d/meson.build b/raysect/core/math/function/vector3d/function2d/meson.build new file mode 100644 index 00000000..786a0bbd --- /dev/null +++ b/raysect/core/math/function/vector3d/function2d/meson.build @@ -0,0 +1,30 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/vector3d/function2d' + +# source files +py_files = ['__init__.py'] +pyx_files = ['autowrap.pyx', 'base.pyx', 'blend.pyx', 'constant.pyx', 'utility.pyx'] +pxd_files = ['__init__.pxd', 'autowrap.pxd', 'base.pxd', 'blend.pxd', 'constant.pxd', 'utility.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('tests') diff --git a/raysect/core/math/function/vector3d/function2d/tests/meson.build b/raysect/core/math/function/vector3d/function2d/tests/meson.build new file mode 100644 index 00000000..4a92b327 --- /dev/null +++ b/raysect/core/math/function/vector3d/function2d/tests/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/vector3d/function2d/tests' + +# source files +py_files = ['__init__.py', 'test_autowrap.py', 'test_base.py', 'test_constant.py', 'test_float_to_vector3d.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/core/math/function/vector3d/function2d/tests/test_autowrap.py b/raysect/core/math/function/vector3d/function2d/tests/test_autowrap.py index 9f244dc1..47fda6cc 100644 --- a/raysect/core/math/function/vector3d/function2d/tests/test_autowrap.py +++ b/raysect/core/math/function/vector3d/function2d/tests/test_autowrap.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function2d/tests/test_base.py b/raysect/core/math/function/vector3d/function2d/tests/test_base.py index 0649dc3a..5f4a5380 100644 --- a/raysect/core/math/function/vector3d/function2d/tests/test_base.py +++ b/raysect/core/math/function/vector3d/function2d/tests/test_base.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function2d/tests/test_constant.py b/raysect/core/math/function/vector3d/function2d/tests/test_constant.py index 00d7f062..a2e93ebb 100644 --- a/raysect/core/math/function/vector3d/function2d/tests/test_constant.py +++ b/raysect/core/math/function/vector3d/function2d/tests/test_constant.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function2d/tests/test_float_to_vector3d.py b/raysect/core/math/function/vector3d/function2d/tests/test_float_to_vector3d.py index 3112c5a0..a4895c05 100644 --- a/raysect/core/math/function/vector3d/function2d/tests/test_float_to_vector3d.py +++ b/raysect/core/math/function/vector3d/function2d/tests/test_float_to_vector3d.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function2d/utility.pxd b/raysect/core/math/function/vector3d/function2d/utility.pxd index 9647e92d..37ca19c2 100644 --- a/raysect/core/math/function/vector3d/function2d/utility.pxd +++ b/raysect/core/math/function/vector3d/function2d/utility.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function2d/utility.pyx b/raysect/core/math/function/vector3d/function2d/utility.pyx index 7c0446dd..f9850f27 100644 --- a/raysect/core/math/function/vector3d/function2d/utility.pyx +++ b/raysect/core/math/function/vector3d/function2d/utility.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function3d/__init__.pxd b/raysect/core/math/function/vector3d/function3d/__init__.pxd index a554aea0..6ec9a9de 100644 --- a/raysect/core/math/function/vector3d/function3d/__init__.pxd +++ b/raysect/core/math/function/vector3d/function3d/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function3d/autowrap.pxd b/raysect/core/math/function/vector3d/function3d/autowrap.pxd index ef319211..e36d1f89 100644 --- a/raysect/core/math/function/vector3d/function3d/autowrap.pxd +++ b/raysect/core/math/function/vector3d/function3d/autowrap.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function3d/autowrap.pyx b/raysect/core/math/function/vector3d/function3d/autowrap.pyx index 2c1b276a..fa604350 100644 --- a/raysect/core/math/function/vector3d/function3d/autowrap.pyx +++ b/raysect/core/math/function/vector3d/function3d/autowrap.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function3d/base.pxd b/raysect/core/math/function/vector3d/function3d/base.pxd index c22778b1..95f4b0e8 100644 --- a/raysect/core/math/function/vector3d/function3d/base.pxd +++ b/raysect/core/math/function/vector3d/function3d/base.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function3d/base.pyx b/raysect/core/math/function/vector3d/function3d/base.pyx index 79242d5d..83e0f604 100644 --- a/raysect/core/math/function/vector3d/function3d/base.pyx +++ b/raysect/core/math/function/vector3d/function3d/base.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -66,31 +66,34 @@ cdef class Function3D(Vector3DFunction): """ return self.evaluate(x, y, z) - def __add__(object a, object b): - if is_callable(a) or isinstance(a, Vector3D): - if is_callable(b) or isinstance(b, Vector3D): - return AddFunction3D(a, b) + def __add__(self, object b): + if is_callable(b) or isinstance(b, Vector3D): + return AddFunction3D(self, b) return NotImplemented - def __sub__(object a, object b): - if is_callable(a) or isinstance(a, Vector3D): - if is_callable(b) or isinstance(b, Vector3D): - return SubtractFunction3D(a, b) - return NotImplemented + def __radd__(self, object a): + return self.__add__(a) - def __mul__(object a, object b): - if is_callable(a) or isinstance(a, Vector3D): - if float_is_callable(b) or isinstance(b, numbers.Real): - return MultiplyFunction3D(a, b) + def __sub__(self, object b): if is_callable(b) or isinstance(b, Vector3D): - if float_is_callable(a) or isinstance(a, numbers.Real): - return MultiplyFunction3D(b, a) + return SubtractFunction3D(self, b) return NotImplemented - def __truediv__(object a, object b): + def __rsub__(self, object a): if is_callable(a) or isinstance(a, Vector3D): - if float_is_callable(b) or isinstance(b, numbers.Real): - return DivideFunction3D(a, b) + return SubtractFunction3D(a, self) + + def __mul__(self, object b): + if float_is_callable(b) or isinstance(b, numbers.Real): + return MultiplyFunction3D(self, b) + return NotImplemented + + def __rmul__(self, object a): + return self.__mul__(a) + + def __truediv__(self, object b): + if float_is_callable(b) or isinstance(b, numbers.Real): + return DivideFunction3D(self, b) return NotImplemented def __neg__(self): diff --git a/raysect/core/math/function/vector3d/function3d/blend.pxd b/raysect/core/math/function/vector3d/function3d/blend.pxd index 160a96bd..16efa436 100644 --- a/raysect/core/math/function/vector3d/function3d/blend.pxd +++ b/raysect/core/math/function/vector3d/function3d/blend.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function3d/blend.pyx b/raysect/core/math/function/vector3d/function3d/blend.pyx index 5f5a1ae7..a44f3bba 100644 --- a/raysect/core/math/function/vector3d/function3d/blend.pyx +++ b/raysect/core/math/function/vector3d/function3d/blend.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function3d/constant.pxd b/raysect/core/math/function/vector3d/function3d/constant.pxd index 937b3086..9173094e 100644 --- a/raysect/core/math/function/vector3d/function3d/constant.pxd +++ b/raysect/core/math/function/vector3d/function3d/constant.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function3d/constant.pyx b/raysect/core/math/function/vector3d/function3d/constant.pyx index 051bd8bb..b39749f4 100644 --- a/raysect/core/math/function/vector3d/function3d/constant.pyx +++ b/raysect/core/math/function/vector3d/function3d/constant.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function3d/meson.build b/raysect/core/math/function/vector3d/function3d/meson.build new file mode 100644 index 00000000..d04d5389 --- /dev/null +++ b/raysect/core/math/function/vector3d/function3d/meson.build @@ -0,0 +1,30 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/vector3d/function3d' + +# source files +py_files = ['__init__.py'] +pyx_files = ['autowrap.pyx', 'base.pyx', 'blend.pyx', 'constant.pyx', 'utility.pyx'] +pxd_files = ['__init__.pxd', 'autowrap.pxd', 'base.pxd', 'blend.pxd', 'constant.pxd', 'utility.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('tests') diff --git a/raysect/core/math/function/vector3d/function3d/tests/meson.build b/raysect/core/math/function/vector3d/function3d/tests/meson.build new file mode 100644 index 00000000..6aac64aa --- /dev/null +++ b/raysect/core/math/function/vector3d/function3d/tests/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/vector3d/function3d/tests' + +# source files +py_files = ['__init__.py', 'test_autowrap.py', 'test_base.py', 'test_constant.py', 'test_float_to_vector3d.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/core/math/function/vector3d/function3d/tests/test_autowrap.py b/raysect/core/math/function/vector3d/function3d/tests/test_autowrap.py index 5836be92..9d8f3732 100644 --- a/raysect/core/math/function/vector3d/function3d/tests/test_autowrap.py +++ b/raysect/core/math/function/vector3d/function3d/tests/test_autowrap.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function3d/tests/test_base.py b/raysect/core/math/function/vector3d/function3d/tests/test_base.py index d94177af..c1a981ff 100644 --- a/raysect/core/math/function/vector3d/function3d/tests/test_base.py +++ b/raysect/core/math/function/vector3d/function3d/tests/test_base.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function3d/tests/test_constant.py b/raysect/core/math/function/vector3d/function3d/tests/test_constant.py index 8f945fd8..b2b3ddfb 100644 --- a/raysect/core/math/function/vector3d/function3d/tests/test_constant.py +++ b/raysect/core/math/function/vector3d/function3d/tests/test_constant.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function3d/tests/test_float_to_vector3d.py b/raysect/core/math/function/vector3d/function3d/tests/test_float_to_vector3d.py index b619520a..2b3ba3e9 100644 --- a/raysect/core/math/function/vector3d/function3d/tests/test_float_to_vector3d.py +++ b/raysect/core/math/function/vector3d/function3d/tests/test_float_to_vector3d.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function3d/utility.pxd b/raysect/core/math/function/vector3d/function3d/utility.pxd index 7caa75ca..3ff5813c 100644 --- a/raysect/core/math/function/vector3d/function3d/utility.pxd +++ b/raysect/core/math/function/vector3d/function3d/utility.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/function3d/utility.pyx b/raysect/core/math/function/vector3d/function3d/utility.pyx index 891d93af..3f01fdf3 100644 --- a/raysect/core/math/function/vector3d/function3d/utility.pyx +++ b/raysect/core/math/function/vector3d/function3d/utility.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/function/vector3d/meson.build b/raysect/core/math/function/vector3d/meson.build new file mode 100644 index 00000000..a1c9fd33 --- /dev/null +++ b/raysect/core/math/function/vector3d/meson.build @@ -0,0 +1,32 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/function/vector3d' + +# source files +py_files = ['__init__.py'] +pyx_files = ['base.pyx'] +pxd_files = ['__init__.pxd', 'base.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('function1d') +subdir('function2d') +subdir('function3d') diff --git a/raysect/core/math/meson.build b/raysect/core/math/meson.build new file mode 100644 index 00000000..98bc930a --- /dev/null +++ b/raysect/core/math/meson.build @@ -0,0 +1,34 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math' + +# source files +py_files = ['__init__.py'] +pyx_files = ['_mat4.pyx', '_vec3.pyx', 'affinematrix.pyx', 'normal.pyx', 'point.pyx', 'polygon.pyx', 'quaternion.pyx', 'random.pyx', 'statsarray.pyx', 'transform.pyx', 'units.pyx', 'vector.pyx'] +pxd_files = ['__init__.pxd', '_mat4.pxd', '_vec3.pxd', 'affinematrix.pxd', 'normal.pxd', 'point.pxd', 'polygon.pxd', 'quaternion.pxd', 'random.pxd', 'statsarray.pxd', 'transform.pxd', 'units.pxd', 'vector.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('cython') +subdir('function') +subdir('sampler') +subdir('spatial') +subdir('tests') diff --git a/raysect/core/math/normal.pxd b/raysect/core/math/normal.pxd index b30878f0..98ceb5bc 100644 --- a/raysect/core/math/normal.pxd +++ b/raysect/core/math/normal.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -33,30 +33,20 @@ from raysect.core.math._vec3 cimport _Vec3 from raysect.core.math.vector cimport Vector3D from raysect.core.math.affinematrix cimport AffineMatrix3D + cdef class Normal3D(_Vec3): cpdef Vector3D cross(self, _Vec3 v) - cpdef Normal3D normalise(self) - cpdef Normal3D transform(self, AffineMatrix3D m) - cpdef Normal3D transform_with_inverse(self, AffineMatrix3D m) - cdef Normal3D neg(self) - cdef Normal3D add(self, _Vec3 v) - cdef Normal3D sub(self, _Vec3 v) - cdef Normal3D mul(self, double m) - cdef Normal3D div(self, double m) - cpdef Normal3D copy(self) - cpdef Vector3D as_vector(self) - cpdef Vector3D orthogonal(self) diff --git a/raysect/core/math/normal.pyx b/raysect/core/math/normal.pyx index c0045a7b..eb680668 100644 --- a/raysect/core/math/normal.pyx +++ b/raysect/core/math/normal.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -34,6 +34,7 @@ cimport cython from libc.math cimport sqrt, fabs from raysect.core.math.vector cimport new_vector3d + cdef class Normal3D(_Vec3): """ Represents a normal vector in 3D affine space. @@ -83,117 +84,103 @@ cdef class Normal3D(_Vec3): return self.x == n.x and self.y == n.y and self.z == n.z elif op == 3: # __ne__() return self.x != n.x or self.y != n.y or self.z != n.z - else: - return NotImplemented + + return NotImplemented def __neg__(self): """Returns a normal with the reverse orientation.""" - return new_normal3d(-self.x, - -self.y, - -self.z) + return new_normal3d(-self.x, -self.y, -self.z) - def __add__(object x, object y): + def __add__(self, object y): """Addition operator.""" - cdef _Vec3 vx, vy - - if isinstance(x, _Vec3) and isinstance(y, _Vec3): + cdef _Vec3 v - vx = <_Vec3>x - vy = <_Vec3>y + if isinstance(y, _Vec3): + v = <_Vec3>y + return new_normal3d(self.x + v.x, self.y + v.y, self.z + v.z) - return new_normal3d(vx.x + vy.x, - vx.y + vy.y, - vx.z + vy.z) - - else: - - return NotImplemented + return NotImplemented + + def __radd__(self, object x): + """Reverse addition operator.""" + + return self.__add__(x) - def __sub__(object x, object y): + def __sub__(self, object y): """Subtract operator.""" - cdef _Vec3 vx, vy + cdef _Vec3 v - if isinstance(x, _Vec3) and isinstance(y, _Vec3): + if isinstance(y, _Vec3): + v = <_Vec3>y + return new_normal3d(self.x - v.x, self.y - v.y, self.z - v.z) - vx = <_Vec3>x - vy = <_Vec3>y + return NotImplemented - return new_normal3d(vx.x - vy.x, - vx.y - vy.y, - vx.z - vy.z) + def __rsub__(self, object x): + """Reverse subtract operator.""" - else: + cdef _Vec3 v - return NotImplemented + if isinstance(x, _Vec3): + v = <_Vec3>x + return new_normal3d(v.x - self.x, v.y - self.y, v.z - self.z) + + return NotImplemented - def __mul__(object x, object y): + def __mul__(self, object y): """Multiply operator.""" cdef double s - cdef Normal3D v - cdef AffineMatrix3D m, minv - if isinstance(x, numbers.Real) and isinstance(y, Normal3D): - - s = x - v = y - - return new_normal3d(s * v.x, - s * v.y, - s * v.z) + if isinstance(y, numbers.Real): + s = y + return new_normal3d(s * self.x, s * self.y, s * self.z) - elif isinstance(x, Normal3D) and isinstance(y, numbers.Real): + return NotImplemented - s = y - v = x + def __rmul__(self, object x): + """Reverse multiply operator.""" - return new_normal3d(s * v.x, - s * v.y, - s * v.z) + cdef: + double s + AffineMatrix3D m, minv - elif isinstance(x, AffineMatrix3D) and isinstance(y, Normal3D): + if isinstance(x, numbers.Real): + s = x + return new_normal3d(s * self.x, s * self.y, s * self.z) + elif isinstance(x, AffineMatrix3D): m = x - v = y - minv = m.inverse() - return new_normal3d(minv.m[0][0] * v.x + minv.m[1][0] * v.y + minv.m[2][0] * v.z, - minv.m[0][1] * v.x + minv.m[1][1] * v.y + minv.m[2][1] * v.z, - minv.m[0][2] * v.x + minv.m[1][2] * v.y + minv.m[2][2] * v.z) + return new_normal3d( + minv.m[0][0] * self.x + minv.m[1][0] * self.y + minv.m[2][0] * self.z, + minv.m[0][1] * self.x + minv.m[1][1] * self.y + minv.m[2][1] * self.z, + minv.m[0][2] * self.x + minv.m[1][2] * self.y + minv.m[2][2] * self.z + ) - else: - - return NotImplemented + return NotImplemented @cython.cdivision(True) - def __truediv__(object x, object y): + def __truediv__(self, object y): """Division operator.""" cdef double d - cdef Normal3D v - if isinstance(x, Normal3D) and isinstance(y, numbers.Real): + if isinstance(y, numbers.Real): - d = y + d = y # prevent divide my zero if d == 0.0: - raise ZeroDivisionError("Cannot divide a vector by a zero scalar.") - v = x d = 1.0 / d + return new_normal3d(d * self.x, d * self.y, d * self.z) - return new_normal3d(d * v.x, - d * v.y, - d * v.z) - - else: - - return NotImplemented + return NotImplemented cpdef Vector3D cross(self, _Vec3 v): """ @@ -205,9 +192,11 @@ cdef class Normal3D(_Vec3): :rtype: Vector3D """ - return new_vector3d(self.y * v.z - v.y * self.z, - self.z * v.x - v.z * self.x, - self.x * v.y - v.x * self.y) + return new_vector3d( + self.y * v.z - v.y * self.z, + self.z * v.x - v.z * self.x, + self.x * v.y - v.x * self.y + ) @cython.cdivision(True) cpdef Normal3D normalise(self): @@ -224,15 +213,11 @@ cdef class Normal3D(_Vec3): # if current length is zero, problem is ill defined t = self.x * self.x + self.y * self.y + self.z * self.z if t == 0.0: - raise ZeroDivisionError("A zero length vector can not be normalised as the direction of a zero length vector is undefined.") # normalise and rescale vector t = 1.0 / sqrt(t) - - return new_normal3d(self.x * t, - self.y * t, - self.z * t) + return new_normal3d(self.x * t, self.y * t, self.z * t) cpdef Normal3D transform(self, AffineMatrix3D m): """ @@ -256,9 +241,11 @@ cdef class Normal3D(_Vec3): cdef AffineMatrix3D minv minv = m.inverse() - return new_normal3d(minv.m[0][0] * self.x + minv.m[1][0] * self.y + minv.m[2][0] * self.z, - minv.m[0][1] * self.x + minv.m[1][1] * self.y + minv.m[2][1] * self.z, - minv.m[0][2] * self.x + minv.m[1][2] * self.y + minv.m[2][2] * self.z) + return new_normal3d( + minv.m[0][0] * self.x + minv.m[1][0] * self.y + minv.m[2][0] * self.z, + minv.m[0][1] * self.x + minv.m[1][1] * self.y + minv.m[2][1] * self.z, + minv.m[0][2] * self.x + minv.m[1][2] * self.y + minv.m[2][2] * self.z + ) cpdef Normal3D transform_with_inverse(self, AffineMatrix3D m): """ @@ -277,9 +264,11 @@ cdef class Normal3D(_Vec3): :rtype: Normal3D """ - return new_normal3d(m.m[0][0] * self.x + m.m[1][0] * self.y + m.m[2][0] * self.z, - m.m[0][1] * self.x + m.m[1][1] * self.y + m.m[2][1] * self.z, - m.m[0][2] * self.x + m.m[1][2] * self.y + m.m[2][2] * self.z) + return new_normal3d( + m.m[0][0] * self.x + m.m[1][0] * self.y + m.m[2][0] * self.z, + m.m[0][1] * self.x + m.m[1][1] * self.y + m.m[2][1] * self.z, + m.m[0][2] * self.x + m.m[1][2] * self.y + m.m[2][2] * self.z + ) cdef Normal3D neg(self): """ @@ -289,9 +278,7 @@ cdef class Normal3D(_Vec3): to the equivalent python operator. """ - return new_normal3d(-self.x, - -self.y, - -self.z) + return new_normal3d(-self.x, -self.y, -self.z) cdef Normal3D add(self, _Vec3 v): """ @@ -301,9 +288,7 @@ cdef class Normal3D(_Vec3): to the equivalent python operator. """ - return new_normal3d(self.x + v.x, - self.y + v.y, - self.z + v.z) + return new_normal3d(self.x + v.x, self.y + v.y, self.z + v.z) cdef Normal3D sub(self, _Vec3 v): """ @@ -313,9 +298,7 @@ cdef class Normal3D(_Vec3): to the equivalent python operator. """ - return new_normal3d(self.x - v.x, - self.y - v.y, - self.z - v.z) + return new_normal3d(self.x - v.x, self.y - v.y, self.z - v.z) cdef Normal3D mul(self, double m): """ @@ -325,9 +308,7 @@ cdef class Normal3D(_Vec3): to the equivalent python operator. """ - return new_normal3d(self.x * m, - self.y * m, - self.z * m) + return new_normal3d(self.x * m, self.y * m, self.z * m) @cython.cdivision(True) cdef Normal3D div(self, double d): @@ -339,14 +320,10 @@ cdef class Normal3D(_Vec3): """ if d == 0.0: - raise ZeroDivisionError("Cannot divide a vector by a zero scalar.") d = 1.0 / d - - return new_normal3d(self.x * d, - self.y * d, - self.z * d) + return new_normal3d(self.x * d, self.y * d, self.z * d) cpdef Normal3D copy(self): """ @@ -355,9 +332,7 @@ cdef class Normal3D(_Vec3): :rtype: Normal3D """ - return new_normal3d(self.x, - self.y, - self.z) + return new_normal3d(self.x, self.y, self.z) cpdef Vector3D as_vector(self): """ @@ -366,9 +341,7 @@ cdef class Normal3D(_Vec3): :rtype: Vector3D """ - return new_vector3d(self.x, - self.y, - self.z) + return new_vector3d(self.x, self.y, self.z) cpdef Vector3D orthogonal(self): """ diff --git a/raysect/core/math/point.pxd b/raysect/core/math/point.pxd index dc7840bf..3665eecc 100644 --- a/raysect/core/math/point.pxd +++ b/raysect/core/math/point.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -38,19 +38,12 @@ cdef class Point3D: cdef public double x, y, z cpdef Vector3D vector_to(self, Point3D p) - cpdef double distance_to(self, Point3D p) - cpdef Point3D transform(self, AffineMatrix3D m) - cdef Point3D add(self, _Vec3 v) - cdef Point3D sub(self, _Vec3 v) - cpdef Point3D copy(self) - cdef double get_index(self, int index) nogil - cdef void set_index(self, int index, double value) nogil @@ -75,19 +68,12 @@ cdef class Point2D: cdef public double x, y cpdef Vector2D vector_to(self, Point2D p) - cpdef double distance_to(self, Point2D p) - # cpdef Point3D transform(self, AffineMatrix3D m) - cdef Point2D add(self, Vector2D v) - cdef Point2D sub(self, Vector2D v) - cpdef Point2D copy(self) - cdef double get_index(self, int index) nogil - cdef void set_index(self, int index, double value) nogil diff --git a/raysect/core/math/point.pyx b/raysect/core/math/point.pyx index 7ebdc2b2..c1089302 100644 --- a/raysect/core/math/point.pyx +++ b/raysect/core/math/point.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -59,7 +59,6 @@ cdef class Point3D: >>> from raysect.core import Point3D >>> a = Point3D(0, 1, 2) - """ def __init__(self, double x=0.0, double y=0.0, double z=0.0): @@ -86,8 +85,8 @@ cdef class Point3D: return self.x == p.x and self.y == p.y and self.z == p.z elif op == 3: # __ne__() return self.x != p.x or self.y != p.y or self.z != p.z - else: - return NotImplemented + + return NotImplemented def __getitem__(self, int i): """Returns the point coordinates by index ([0,1,2] -> [x,y,z]). @@ -103,8 +102,8 @@ cdef class Point3D: return self.y elif i == 2: return self.z - else: - raise IndexError("Index out of range [0, 2].") + + raise IndexError("Index out of range [0, 2].") def __setitem__(self, int i, double value): """Sets the point coordinates by index ([0,1,2] -> [x,y,z]). @@ -132,87 +131,70 @@ cdef class Point3D: >>> x, y, z (0.0, 1.0, 2.0) """ + yield self.x yield self.y yield self.z - def __add__(object x, object y): + def __add__(self, object y): """Addition operator. >>> Point3D(1, 0, 0) + Vector3D(0, 1, 0) Point3D(1.0, 1.0, 0.0) """ - cdef Point3D p cdef _Vec3 v - if isinstance(x, Point3D) and isinstance(y, _Vec3): - - p = x - v = <_Vec3>y - - else: - - return NotImplemented + if isinstance(y, _Vec3): + v = <_Vec3> y + return new_point3d(self.x + v.x, self.y + v.y, self.z + v.z) - return new_point3d(p.x + v.x, - p.y + v.y, - p.z + v.z) + return NotImplemented - def __sub__(object x, object y): + def __sub__(self, object y): """Subtraction operator. >>> Point3D(1, 0, 0) - Vector3D(0, 1, 0) Point3D(1.0, -1.0, 0.0) """ - cdef Point3D p cdef _Vec3 v - if isinstance(x, Point3D) and isinstance(y, _Vec3): - - p = x + if isinstance(y, _Vec3): v = <_Vec3>y + return new_point3d(self.x - v.x, self.y - v.y, self.z - v.z) - return new_point3d(p.x - v.x, - p.y - v.y, - p.z - v.z) - - else: - - return NotImplemented + return NotImplemented @cython.cdivision(True) - def __mul__(object x, object y): + def __rmul__(self, object x): """Multiplication operator. :param AffineMatrix3D x: transformation matrix x - :param Point3D y: point to transform :return: Matrix multiplication of a 3D transformation matrix with the input point. :rtype: Point3D """ cdef AffineMatrix3D m - cdef Point3D v cdef double w - if isinstance(x, AffineMatrix3D) and isinstance(y, Point3D): + if isinstance(x, AffineMatrix3D): m = x - v = y # 4th element of homogeneous coordinate - w = m.m[3][0] * v.x + m.m[3][1] * v.y + m.m[3][2] * v.z + m.m[3][3] + w = m.m[3][0] * self.x + m.m[3][1] * self.y + m.m[3][2] * self.z + m.m[3][3] if w == 0.0: - raise ZeroDivisionError("Bad matrix transform, 4th element of homogeneous coordinate is zero.") # pre divide for speed (dividing is much slower than multiplying) w = 1.0 / w - return new_point3d((m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z + m.m[0][3]) * w, - (m.m[1][0] * v.x + m.m[1][1] * v.y + m.m[1][2] * v.z + m.m[1][3]) * w, - (m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z + m.m[2][3]) * w) + return new_point3d( + (m.m[0][0] * self.x + m.m[0][1] * self.y + m.m[0][2] * self.z + m.m[0][3]) * w, + (m.m[1][0] * self.x + m.m[1][1] * self.y + m.m[1][2] * self.z + m.m[1][3]) * w, + (m.m[2][0] * self.x + m.m[2][1] * self.y + m.m[2][2] * self.z + m.m[2][3]) * w + ) return NotImplemented @@ -244,9 +226,7 @@ cdef class Point3D: """ - return new_vector3d(p.x - self.x, - p.y - self.y, - p.z - self.z) + return new_vector3d(p.x - self.x, p.y - self.y, p.z - self.z) cpdef double distance_to(self, Point3D p): """ @@ -293,15 +273,15 @@ cdef class Point3D: # 4th element of homogeneous coordinate w = m.m[3][0] * self.x + m.m[3][1] * self.y + m.m[3][2] * self.z + m.m[3][3] if w == 0.0: - raise ZeroDivisionError("Bad matrix transform, 4th element of homogeneous coordinate is zero.") # pre divide for speed (dividing is much slower than multiplying) w = 1.0 / w - - return new_point3d((m.m[0][0] * self.x + m.m[0][1] * self.y + m.m[0][2] * self.z + m.m[0][3]) * w, - (m.m[1][0] * self.x + m.m[1][1] * self.y + m.m[1][2] * self.z + m.m[1][3]) * w, - (m.m[2][0] * self.x + m.m[2][1] * self.y + m.m[2][2] * self.z + m.m[2][3]) * w) + return new_point3d( + (m.m[0][0] * self.x + m.m[0][1] * self.y + m.m[0][2] * self.z + m.m[0][3]) * w, + (m.m[1][0] * self.x + m.m[1][1] * self.y + m.m[1][2] * self.z + m.m[1][3]) * w, + (m.m[2][0] * self.x + m.m[2][1] * self.y + m.m[2][2] * self.z + m.m[2][3]) * w + ) cdef Point3D add(self, _Vec3 v): """ @@ -311,9 +291,7 @@ cdef class Point3D: to the equivalent python operator. """ - return new_point3d(self.x + v.x, - self.y + v.y, - self.z + v.z) + return new_point3d(self.x + v.x, self.y + v.y, self.z + v.z) cdef Point3D sub(self, _Vec3 v): """ @@ -323,9 +301,7 @@ cdef class Point3D: to the equivalent python operator. """ - return new_point3d(self.x - v.x, - self.y - v.y, - self.z - v.z) + return new_point3d(self.x - v.x, self.y - v.y, self.z - v.z) cpdef Point3D copy(self): """ @@ -340,9 +316,7 @@ cdef class Point3D: Point3D(0.0, 1.0, 2.0) """ - return new_point3d(self.x, - self.y, - self.z) + return new_point3d(self.x, self.y, self.z) cdef double get_index(self, int index) nogil: """ @@ -404,7 +378,6 @@ cdef class Point2D: """ def __init__(self, double x=0.0, double y=0.0): - self.x = x self.y = y @@ -441,8 +414,8 @@ cdef class Point2D: return self.x elif i == 1: return self.y - else: - raise IndexError("Index out of range [0, 1].") + + raise IndexError("Index out of range [0, 1].") def __setitem__(self, int i, double value): """Sets the point coordinates by index ([0,1] -> [x,y]). @@ -469,67 +442,54 @@ cdef class Point2D: (1.0, 1.0) """ + yield self.x yield self.y - def __add__(object x, object y): + def __add__(self, object y): """Addition operator. >>> Point2D(1, 0) + Vector2D(0, 1) Point2D(1.0, 1.0) """ - cdef Point2D p cdef Vector2D v - if isinstance(x, Point2D) and isinstance(y, Vector2D): - - p = x + if isinstance(y, Vector2D): v = y + return new_point2d(self.x + v.x, self.y + v.y) - else: - - return NotImplemented - - return new_point2d(p.x + v.x, p.y + v.y) + return NotImplemented - def __sub__(object x, object y): + def __sub__(self, object y): """Subtraction operator. >>> Point2D(1, 0) - Vector2D(0, 1) Point2D(1.0, -1.0) """ - cdef Point2D p cdef Vector2D v - if isinstance(x, Point2D) and isinstance(y, Vector2D): - - p = x + if isinstance(y, Vector2D): v = y + return new_point2d(self.x - v.x, self.y - v.y) - return new_point2d(p.x - v.x, p.y - v.y) - - else: - - return NotImplemented + return NotImplemented @cython.cdivision(True) - def __mul__(object x, object y): + def __rmul__(self, object x): """Multiply operator.""" - raise NotImplemented + return NotImplemented # cdef AffineMatrix3D m - # cdef Point3D v # cdef double w # - # if isinstance(x, AffineMatrix3D) and isinstance(y, Point3D): + # if isinstance(x, AffineMatrix3D): # # m = x - # v = y # # # 4th element of homogeneous coordinate - # w = m.m[3][0] * v.x + m.m[3][1] * v.y + m.m[3][2] * v.z + m.m[3][3] + # w = m.m[3][0] * self.x + m.m[3][1] * self.y + m.m[3][2] * self.z + m.m[3][3] # if w == 0.0: # # raise ZeroDivisionError("Bad matrix transform, 4th element of homogeneous coordinate is zero.") @@ -537,9 +497,9 @@ cdef class Point2D: # # pre divide for speed (dividing is much slower than multiplying) # w = 1.0 / w # - # return new_point3d((m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z + m.m[0][3]) * w, - # (m.m[1][0] * v.x + m.m[1][1] * v.y + m.m[1][2] * v.z + m.m[1][3]) * w, - # (m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z + m.m[2][3]) * w) + # return new_point3d((m.m[0][0] * self.x + m.m[0][1] * self.y + m.m[0][2] * self.z + m.m[0][3]) * w, + # (m.m[1][0] * self.x + m.m[1][1] * self.y + m.m[1][2] * self.z + m.m[1][3]) * w, + # (m.m[2][0] * self.x + m.m[2][1] * self.y + m.m[2][2] * self.z + m.m[2][3]) * w) # # return NotImplemented diff --git a/raysect/core/math/polygon.pxd b/raysect/core/math/polygon.pxd index c21befce..cf7fba87 100644 --- a/raysect/core/math/polygon.pxd +++ b/raysect/core/math/polygon.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/polygon.pyx b/raysect/core/math/polygon.pyx index be2c0610..01c245b3 100644 --- a/raysect/core/math/polygon.pyx +++ b/raysect/core/math/polygon.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/quaternion.pxd b/raysect/core/math/quaternion.pxd index 50972181..2c9ec72e 100644 --- a/raysect/core/math/quaternion.pxd +++ b/raysect/core/math/quaternion.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -38,41 +38,23 @@ cdef class Quaternion: cdef public double x, y, z, s cpdef Quaternion copy(self) - cpdef Quaternion conjugate(self) - cpdef Quaternion inverse(self) - cpdef Quaternion normalise(self) - cpdef bint is_unit(self, double tolerance=*) - cpdef Quaternion transform(self, AffineMatrix3D m) - cpdef AffineMatrix3D as_matrix(self) - cpdef Quaternion quaternion_to(self, Quaternion q) - cdef Quaternion neg(self) - cdef Quaternion add(self, Quaternion q) - cdef Quaternion sub(self, Quaternion q) - cdef Quaternion mul_quaternion(self, Quaternion q) - cdef Quaternion mul_scalar(self, double d) - cdef Quaternion div_quaternion(self, Quaternion q) - cdef Quaternion div_scalar(self, double d) - cdef Vector3D get_axis(self) - cdef double get_angle(self) - cdef double get_length(self) nogil - cdef object set_length(self, double v) @@ -96,4 +78,4 @@ cdef inline Quaternion new_quaternion(double x, double y, double z, double s): cdef Quaternion new_quaternion_from_matrix(AffineMatrix3D matrix) -cdef Quaternion new_quaternion_from_axis_angle(Vector3D axis, double angle) \ No newline at end of file +cdef Quaternion new_quaternion_from_axis_angle(Vector3D axis, double angle) diff --git a/raysect/core/math/quaternion.pyx b/raysect/core/math/quaternion.pyx index 76038a78..dec92228 100644 --- a/raysect/core/math/quaternion.pyx +++ b/raysect/core/math/quaternion.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,13 +31,14 @@ import numbers cimport cython -from libc.math cimport sqrt, sin, cos, asin, acos, atan2, fabs, M_PI, copysign +from libc.math cimport sqrt, sin, cos, acos, fabs from raysect.core.math.vector cimport new_vector3d from raysect.core.math.affinematrix cimport new_affinematrix3d, AffineMatrix3D -DEF RAD2DEG = 57.29577951308232000 # 180 / pi -DEF DEG2RAD = 0.017453292519943295 # pi / 180 + +cdef const double RAD2DEG = 57.29577951308232000 # 180 / pi +cdef const double DEG2RAD = 0.017453292519943295 # pi / 180 cdef class Quaternion: @@ -72,8 +73,8 @@ cdef class Quaternion: return self.z elif i == 3: return self.s - else: - raise IndexError("Index out of range [0, 3].") + + raise IndexError("Index out of range [0, 3].") def __setitem__(self, int i, double value): """Sets the quaternion coordinates by index ([0,1,2,3] -> [x,y,z,s]). @@ -105,6 +106,7 @@ cdef class Quaternion: >>> x, y, z, s (0.0, 1.0, 2.0, 3.0) """ + yield self.x yield self.y yield self.z @@ -127,7 +129,7 @@ cdef class Quaternion: return new_quaternion(-self.x, -self.y, -self.z, -self.s) - def __eq__(object x, object y): + def __eq__(self, object y): """ Equality operator. @@ -137,18 +139,15 @@ cdef class Quaternion: True """ - cdef Quaternion q1, q2 - - if isinstance(x, Quaternion) and isinstance(y, Quaternion): + cdef Quaternion q - q1 = x - q2 = y - return q1.x == q2.x and q1.y == q2.y and q1.z == q2.z and q1.s == q2.s + if isinstance(y, Quaternion): + q = y + return self.x == q.x and self.y == q.y and self.z == q.z and self.s == q.s - else: - raise TypeError('A quaternion can only be equality tested against another quaternion.') + raise TypeError('A quaternion can only be equality tested against another quaternion.') - def __add__(object x, object y): + def __add__(self, object y): """ Addition operator. @@ -158,18 +157,15 @@ cdef class Quaternion: Quaternion(0.0, 1.0, 0.0, 1.0) """ - cdef Quaternion q1, q2 + cdef Quaternion q - if isinstance(x, Quaternion) and isinstance(y, Quaternion): + if isinstance(y, Quaternion): + q = y + return new_quaternion(self.x + q.x, self.y + q.y, self.z + q.z, self.s + q.s) - q1 = x - q2 = y - return new_quaternion(q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.s + q2.s) + return NotImplemented - else: - return NotImplemented - - def __sub__(object x, object y): + def __sub__(self, object y): """Subtraction operator. .. code-block:: pycon @@ -178,18 +174,15 @@ cdef class Quaternion: Quaternion(0.0, -1.0, 0, 1.0) """ - cdef Quaternion q1, q2 + cdef Quaternion q - if isinstance(x, Quaternion) and isinstance(y, Quaternion): + if isinstance(y, Quaternion): + q = y + return new_quaternion(self.x - q.x, self.y - q.y, self.z - q.z, self.s - q.s) - q1 = x - q2 = y - return new_quaternion(q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.s - q2.s) + return NotImplemented - else: - return NotImplemented - - def __mul__(object x, object y): + def __mul__(self, object y): """Multiplication operator. .. code-block:: pycon @@ -201,31 +194,37 @@ cdef class Quaternion: """ cdef double s - cdef Quaternion q1, q2 + cdef Quaternion q + + if isinstance(y, numbers.Real): + s = y + return self.mul_scalar(s) - if isinstance(x, numbers.Real) and isinstance(y, Quaternion): + elif isinstance(y, Quaternion): + q = y + return self.mul_quaternion(q) - s = x - q1 = y - return q1.mul_scalar(s) + return NotImplemented - elif isinstance(x, Quaternion) and isinstance(y, numbers.Real): + def __rmul__(self, object x): + """Reverse multiplication operator. - q1 = x - s = y - return q1.mul_scalar(s) + .. code-block:: pycon - elif isinstance(x, Quaternion) and isinstance(y, Quaternion): + >>> 2 * Quaternion(0, 0, 1, 1) + Quaternion(0.0, 0.0, 2.0, 2.0) + """ - q1 = x - q2 = y - return q1.mul_quaternion(q2) + cdef double s - else: - return NotImplemented() + if isinstance(x, numbers.Real): + s = x + return self.mul_scalar(s) + + return NotImplemented @cython.cdivision(True) - def __truediv__(object x, object y): + def __truediv__(self, object y): """Division operator. .. code-block:: pycon @@ -237,22 +236,17 @@ cdef class Quaternion: """ cdef double d - cdef Quaternion q1, q2, q2_inv - - if isinstance(x, Quaternion) and isinstance(y, numbers.Real): + cdef Quaternion q + if isinstance(y, numbers.Real): d = y - q1 = x - return q1.div_scalar(d) + return self.div_scalar(d) - elif isinstance(x, Quaternion) and isinstance(y, Quaternion): + elif isinstance(y, Quaternion): + q = y + return self.div_quaternion(q) - q1 = x - q2 = y - return q1.div_quaternion(q2) - - else: - raise TypeError('Unsupported operand type. Expects a real number.') + raise TypeError('Unsupported operand type. Expects a real number.') @property def length(self): @@ -264,34 +258,40 @@ cdef class Quaternion: >>> Quaternion(1, 2, 3, 0).length 3.7416573867739413 """ + return self.get_length() @length.setter def length(self, value): self.set_length(value) - @property def axis(self): """ The axis around which this quaternion rotates. """ + return self.get_axis() @property def angle(self): - """The magnitude of rotation around this quaternion's rotation axis in degrees.""" + """ + The magnitude of rotation around this quaternion's rotation axis in degrees. + """ + return self.get_angle() cpdef Quaternion copy(self): - """Returns a copy of this quaternion.""" + """ + Returns a copy of this quaternion. + """ return new_quaternion(self.x, self.y, self.z, self.s) cpdef Quaternion conjugate(self): """ - Complex conjugate operator. - + Complex conjugate operator. + .. code-block:: pycon >>> Quaternion(1, 2, 3, 0).conjugate() @@ -322,7 +322,7 @@ cdef class Quaternion: The returned quaternion is normalised to have norm length 1.0 - a unit quaternion. .. code-block:: pycon - + >>> a = Quaternion(1, 2, 3, 0) >>> a.normalise() Quaternion(0.26726, 0.53452, 0.80178, 0.0) @@ -345,6 +345,7 @@ cdef class Quaternion: :param float tolerance: The numerical tolerance by which the quaternion norm can differ by 1.0. """ + return fabs(1.0 - self.get_length()) <= tolerance cpdef Quaternion transform(self, AffineMatrix3D m): @@ -409,10 +410,12 @@ cdef class Quaternion: m21 = 2*qy*qz + 2*qx*qs m22 = 1 - 2*qx2 - 2*qy2 - return new_affinematrix3d(m00, m01, m02, 0, - m10, m11, m12, 0, - m20, m21, m22, 0, - 0, 0, 0, 1) + return new_affinematrix3d( + m00, m01, m02, 0, + m10, m11, m12, 0, + m20, m21, m22, 0, + 0, 0, 0, 1 + ) cpdef Quaternion quaternion_to(self, Quaternion q): """ @@ -421,12 +424,12 @@ cdef class Quaternion: This method calculates the quaternion required to map this quaternion onto the supplied quaternion. Both quaternions will be normalised and a normalised quaternion will be returned. - + .. code-block:: pycon - + >>> from raysect.core.math import Quaternion >>> - >>> q1 = Quaternion.from_axis_angle(Vector3D(1,0,0), 10) + >>> q1 = Quaternion.from_axis_angle(Vector3D(1,0,0), 10) >>> q2 = Quaternion.from_axis_angle(Vector3D(1,0,0), 25) >>> d = q1.quaternion_to(q2) >>> d @@ -435,9 +438,9 @@ cdef class Quaternion: 15.000000000000027 >>> d.axis Vector3D(1.0, 0.0, 0.0) - + :param Quaternion q: The target quaternion. - :return: A new Quaternion object representing the specified rotation. + :return: A new Quaternion object representing the specified rotation. """ return q.normalise().mul_quaternion(self.normalise().conjugate()).normalise() @@ -565,7 +568,9 @@ cdef class Quaternion: @cython.cdivision(True) cdef double get_angle(self): - """The magnitude of rotation around this quaternion's rotation axis in degrees.""" + """ + The magnitude of rotation around this quaternion's rotation axis in degrees. + """ cdef Quaternion q = self.normalise() return 2 * acos(q.s) * RAD2DEG @@ -578,6 +583,7 @@ cdef class Quaternion: Use instead of Python attribute access in cython code. """ + return sqrt(self.x * self.x + self.y * self.y + self.z * self.z + self.s * self.s) @cython.cdivision(True) @@ -686,4 +692,4 @@ cdef Quaternion new_quaternion_from_axis_angle(Vector3D axis, double angle): qz = axis.z * sin(theta_2) qs = cos(theta_2) - return new_quaternion(qx, qy, qz, qs) \ No newline at end of file + return new_quaternion(qx, qy, qz, qs) diff --git a/raysect/core/math/random.pxd b/raysect/core/math/random.pxd index 67198a16..5be54b81 100644 --- a/raysect/core/math/random.pxd +++ b/raysect/core/math/random.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/random.pyx b/raysect/core/math/random.pyx index 096acb04..6029fbbf 100644 --- a/raysect/core/math/random.pyx +++ b/raysect/core/math/random.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -96,8 +96,9 @@ from libc.math cimport cos, sin, asin, log, fabs, sqrt, M_PI as PI from libc.stdint cimport uint64_t, int64_t cimport cython -DEF NN = 312 -DEF MM = 156 +cdef enum: + NN = 312 + MM = 156 # The array for the state vector cdef uint64_t mt[NN] diff --git a/raysect/core/math/sampler/__init__.pxd b/raysect/core/math/sampler/__init__.pxd index f7b95ca1..98840aff 100644 --- a/raysect/core/math/sampler/__init__.pxd +++ b/raysect/core/math/sampler/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,5 +31,5 @@ from raysect.core.math.sampler.solidangle cimport * from raysect.core.math.sampler.surface3d cimport * -from raysect.core.math.sampler.targetted cimport * +from raysect.core.math.sampler.targeted cimport * diff --git a/raysect/core/math/sampler/__init__.py b/raysect/core/math/sampler/__init__.py index 23bed925..39b18ae2 100644 --- a/raysect/core/math/sampler/__init__.py +++ b/raysect/core/math/sampler/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,4 +31,4 @@ from .solidangle import * from .surface3d import * -from .targetted import * +from .targeted import * diff --git a/raysect/core/math/sampler/meson.build b/raysect/core/math/sampler/meson.build new file mode 100644 index 00000000..6fea0bca --- /dev/null +++ b/raysect/core/math/sampler/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/sampler' + +# source files +py_files = ['__init__.py'] +pyx_files = ['solidangle.pyx', 'surface3d.pyx', 'targeted.pyx'] +pxd_files = ['__init__.pxd', 'solidangle.pxd', 'surface3d.pxd', 'targeted.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/core/math/sampler/solidangle.pxd b/raysect/core/math/sampler/solidangle.pxd index 146b6072..8a3131c3 100644 --- a/raysect/core/math/sampler/solidangle.pxd +++ b/raysect/core/math/sampler/solidangle.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -29,25 +29,15 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -from libc.math cimport M_PI, M_1_PI, sqrt, sin, cos -from raysect.core.math cimport Point2D, new_point2d, Point3D, new_point3d, Vector3D, new_vector3d -from raysect.core.math.random cimport uniform -from raysect.core.math.cython cimport barycentric_coords, barycentric_interpolation - -DEF R_2_PI = 0.15915494309189535 # 1 / (2 * pi) -DEF R_4_PI = 0.07957747154594767 # 1 / (4 * pi) +from raysect.core.math cimport Vector3D cdef class SolidAngleSampler: cpdef double pdf(self, Vector3D sample) - cdef Vector3D sample(self) - cdef tuple sample_with_pdf(self) - cdef list samples(self, int samples) - cdef list samples_with_pdfs(self, int samples) diff --git a/raysect/core/math/sampler/solidangle.pyx b/raysect/core/math/sampler/solidangle.pyx index 55a76e33..c6a29719 100644 --- a/raysect/core/math/sampler/solidangle.pyx +++ b/raysect/core/math/sampler/solidangle.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -29,14 +29,14 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -from libc.math cimport M_PI, M_1_PI, sqrt, sin, cos, asin +from libc.math cimport M_PI, M_1_PI, sqrt, sin, cos from raysect.core.math cimport Vector3D, new_vector3d from raysect.core.math.random cimport uniform -# TODO: add tests - idea: solve the lighting equation with a uniform emitting surface with each sampler and check the mean radiance is unity -DEF R_2_PI = 0.15915494309189535 # 1 / (2 * pi) -DEF R_4_PI = 0.07957747154594767 # 1 / (4 * pi) +# TODO: add tests - idea: solve the lighting equation with a uniform emitting surface with each sampler and check the mean radiance is unity +cdef const double R_2_PI = 0.15915494309189535 # 1 / (2 * pi) +cdef const double R_4_PI = 0.07957747154594767 # 1 / (4 * pi) cdef class SolidAngleSampler: @@ -73,7 +73,7 @@ cdef class SolidAngleSampler: cpdef double pdf(self, Vector3D sample): """ Generates a pdf for a given sample value. - + Vectors *must* be normalised. :param Vector3D sample: The sample point at which to get the pdf. @@ -242,7 +242,7 @@ cdef class ConeUniformSampler(SolidAngleSampler): Generates a uniform weighted random vector from a cone. The cone is aligned along the z-axis. - + :param angle: Angle of the cone in degrees (default=45). .. code-block:: pycon diff --git a/raysect/core/math/sampler/surface3d.pxd b/raysect/core/math/sampler/surface3d.pxd index fad67d71..3b007989 100644 --- a/raysect/core/math/sampler/surface3d.pxd +++ b/raysect/core/math/sampler/surface3d.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -35,11 +35,8 @@ from raysect.core.math cimport Point3D cdef class SurfaceSampler3D: cdef Point3D sample(self) - cdef tuple sample_with_pdf(self) - cdef list samples(self, int samples) - cdef list samples_with_pdfs(self, int samples) diff --git a/raysect/core/math/sampler/surface3d.pyx b/raysect/core/math/sampler/surface3d.pyx index 23303a30..110a7f86 100644 --- a/raysect/core/math/sampler/surface3d.pyx +++ b/raysect/core/math/sampler/surface3d.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/sampler/targetted.pxd b/raysect/core/math/sampler/targeted.pxd similarity index 91% rename from raysect/core/math/sampler/targetted.pxd rename to raysect/core/math/sampler/targeted.pxd index e85e0d69..b5633b4d 100644 --- a/raysect/core/math/sampler/targetted.pxd +++ b/raysect/core/math/sampler/targeted.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,7 +32,8 @@ cimport numpy as np from raysect.core.math cimport Point3D, Vector3D -cdef class _TargettedSampler: + +cdef class _TargetedSampler: cdef: double _total_weight @@ -41,24 +42,17 @@ cdef class _TargettedSampler: double[::1] _cdf_mv cdef object _validate_targets(self) - cpdef double pdf(self, Point3D point, Vector3D sample) - cdef Vector3D sample(self, Point3D point) - cdef tuple sample_with_pdf(self, Point3D point) - cdef list samples(self, Point3D point, int samples) - cdef list samples_with_pdfs(self, Point3D point, int samples) - cdef object _calculate_cdf(self) - cdef tuple _pick_sphere(self) -cdef class TargettedHemisphereSampler(_TargettedSampler): +cdef class TargetedHemisphereSampler(_TargetedSampler): pass -cdef class TargettedSphereSampler(_TargettedSampler): +cdef class TargetedSphereSampler(_TargetedSampler): pass \ No newline at end of file diff --git a/raysect/core/math/sampler/targetted.pyx b/raysect/core/math/sampler/targeted.pyx similarity index 97% rename from raysect/core/math/sampler/targetted.pyx rename to raysect/core/math/sampler/targeted.pyx index 9faf898e..9dffa327 100644 --- a/raysect/core/math/sampler/targetted.pyx +++ b/raysect/core/math/sampler/targeted.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -34,11 +34,11 @@ cimport numpy as np from raysect.core.math cimport Point3D, Vector3D, AffineMatrix3D from raysect.core.math.random cimport uniform, vector_sphere, vector_cone_uniform, vector_hemisphere_cosine from raysect.core.math.cython cimport find_index, rotate_basis -from libc.math cimport M_PI, M_1_PI, asin, acos, sqrt +from libc.math cimport M_PI, M_1_PI, asin, sqrt cimport cython -cdef class _TargettedSampler: +cdef class _TargetedSampler: def __init__(self, object targets): """ @@ -46,7 +46,7 @@ cdef class _TargettedSampler: Each target tuple consists of (Point3D sphere_centre, double sphere_radius, double weight). - :param list targets: A list of tuples describing spheres for targetted sampling. + :param list targets: A list of tuples describing spheres for targeted sampling. """ self._targets = tuple(targets) @@ -248,16 +248,16 @@ cdef class _TargettedSampler: return self._targets[index] -cdef class TargettedHemisphereSampler(_TargettedSampler): +cdef class TargetedHemisphereSampler(_TargetedSampler): """ - Generates vectors on a hemisphere targetting a set of target spheres. + Generates vectors on a hemisphere targeting a set of target spheres. This sampler takes a list of spheres and corresponding weighting factors. To generate a sample a sphere is randomly selected according the distribution of the sphere weights and launches a ray at the solid angle subtended by the target sphere. - If the targetted sphere intersects with the hemisphere's base plane, lies + If the targeted sphere intersects with the hemisphere's base plane, lies behind the plane, or the origin point from which samples are generated lies inside the target sphere, a sample is randomly selected from the full hemisphere using a cosine weighted distribution. @@ -389,9 +389,9 @@ cdef class TargettedHemisphereSampler(_TargettedSampler): return sample.transform(rotation) -cdef class TargettedSphereSampler(_TargettedSampler): +cdef class TargetedSphereSampler(_TargetedSampler): """ - Generates vectors targetting a set of target spheres. + Generates vectors targeting a set of target spheres. This sampler takes a list of spheres and corresponding weighting factors. To generate a sample a sphere is randomly selected according the diff --git a/raysect/core/math/spatial/__init__.pxd b/raysect/core/math/spatial/__init__.pxd index c6160567..87ff7989 100644 --- a/raysect/core/math/spatial/__init__.pxd +++ b/raysect/core/math/spatial/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/spatial/__init__.py b/raysect/core/math/spatial/__init__.py index 9c638ece..8b7b50bd 100644 --- a/raysect/core/math/spatial/__init__.py +++ b/raysect/core/math/spatial/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/spatial/kdtree2d.pxd b/raysect/core/math/spatial/kdtree2d.pxd index 560dd1ca..c2c7e414 100644 --- a/raysect/core/math/spatial/kdtree2d.pxd +++ b/raysect/core/math/spatial/kdtree2d.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -30,10 +30,10 @@ # POSSIBILITY OF SUCH DAMAGE. from raysect.core.boundingbox cimport BoundingBox2D -from raysect.core.ray cimport Ray from raysect.core.math.point cimport Point2D from libc.stdint cimport int32_t + # c-structure that represent a kd-tree node cdef struct kdnode: @@ -69,56 +69,32 @@ cdef class KDTree2DCore: double _empty_bonus cdef int32_t _build(self, list items, BoundingBox2D bounds, int32_t depth=*) - cdef tuple _split(self, list items, BoundingBox2D bounds) - cdef void _get_edges(self, list items, int32_t axis, int32_t *num_edges, edge **edges_ptr) - cdef void _free_edges(self, edge **edges_ptr) - cdef BoundingBox2D _get_lower_bounds(self, BoundingBox2D bounds, double split, int32_t axis) - cdef BoundingBox2D _get_upper_bounds(self, BoundingBox2D bounds, double split, int32_t axis) - cdef int32_t _new_leaf(self, list ids) - cdef int32_t _new_branch(self, tuple split_solution, int32_t depth) - cdef int32_t _new_node(self) - cpdef bint is_contained(self, Point2D point) - cdef bint _is_contained(self, Point2D point) - cdef bint _is_contained_node(self, int32_t id, Point2D point) - cdef bint _is_contained_branch(self, int32_t id, Point2D point) - cdef bint _is_contained_leaf(self, int32_t id, Point2D point) - cpdef list items_containing(self, Point2D point) - cdef list _items_containing(self, Point2D point) - cdef list _items_containing_node(self, int32_t id, Point2D point) - cdef list _items_containing_branch(self, int32_t id, Point2D point) - cdef list _items_containing_leaf(self, int32_t id, Point2D point) - cdef void _reset(self) - cdef double _read_double(self, object file) - cdef int32_t _read_int32(self, object file) cdef class KDTree2D(KDTree2DCore): cdef bint _is_contained_leaf(self, int32_t id, Point2D point) - cpdef bint _is_contained_items(self, list items, Point2D point) - cdef list _items_containing_leaf(self, int32_t id, Point2D point) - cpdef list _items_containing_items(self, list items, Point2D point) \ No newline at end of file diff --git a/raysect/core/math/spatial/kdtree2d.pyx b/raysect/core/math/spatial/kdtree2d.pyx index 2e26888e..526eee0d 100644 --- a/raysect/core/math/spatial/kdtree2d.pyx +++ b/raysect/core/math/spatial/kdtree2d.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -40,16 +40,20 @@ from libc.stdint cimport int32_t from libc.math cimport log, ceil cimport cython -# this number of nodes will be pre-allocated when the kd-tree is initially created -DEF INITIAL_NODE_COUNT = 128 -# friendly name for first node -DEF ROOT_NODE = 0 +# constants +cdef enum: -# node types -DEF LEAF = -1 # leaf node -DEF X_AXIS = 0 # branch, x-axis split -DEF Y_AXIS = 1 # branch, y-axis split + # this number of nodes will be pre-allocated when the kd-tree is initially created + INITIAL_NODE_COUNT = 128 + + # friendly name for first node + ROOT_NODE = 0 + + # node types + LEAF = -1 # leaf node + X_AXIS = 0 # branch, x-axis split + Y_AXIS = 1 # branch, y-axis split cdef class Item2D: @@ -69,7 +73,6 @@ cdef class Item2D: """ def __init__(self, int32_t id, BoundingBox2D box): - self.id = id self.box = box diff --git a/raysect/core/math/spatial/kdtree3d.pxd b/raysect/core/math/spatial/kdtree3d.pxd index f0706b58..cd80f059 100644 --- a/raysect/core/math/spatial/kdtree3d.pxd +++ b/raysect/core/math/spatial/kdtree3d.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -69,66 +69,37 @@ cdef class KDTree3DCore: double _empty_bonus cdef int32_t _build(self, list items, BoundingBox3D bounds, int32_t depth=*) - cdef tuple _split(self, list items, BoundingBox3D bounds) - cdef void _get_edges(self, list items, int32_t axis, int32_t *num_edges, edge **edges_ptr) - cdef void _free_edges(self, edge **edges_ptr) - cdef BoundingBox3D _get_lower_bounds(self, BoundingBox3D bounds, double split, int32_t axis) - cdef BoundingBox3D _get_upper_bounds(self, BoundingBox3D bounds, double split, int32_t axis) - cdef int32_t _new_leaf(self, list ids) - cdef int32_t _new_branch(self, tuple split_solution, int32_t depth) - cdef int32_t _new_node(self) - cpdef bint is_contained(self, Point3D point) - cdef bint _is_contained(self, Point3D point) - cdef bint _is_contained_node(self, int32_t id, Point3D point) - cdef bint _is_contained_branch(self, int32_t id, Point3D point) - cdef bint _is_contained_leaf(self, int32_t id, Point3D point) - cpdef bint trace(self, Ray ray) - cdef bint _trace(self, Ray ray) - cdef bint _trace_node(self, int32_t id, Ray ray, double min_range, double max_range) - cdef bint _trace_branch(self, int32_t id, Ray ray, double min_range, double max_range) - cdef bint _trace_leaf(self, int32_t id, Ray ray, double max_range) - cpdef list items_containing(self, Point3D point) - cdef list _items_containing(self, Point3D point) - cdef list _items_containing_node(self, int32_t id, Point3D point) - cdef list _items_containing_branch(self, int32_t id, Point3D point) - cdef list _items_containing_leaf(self, int32_t id, Point3D point) - cdef void _reset(self) - cdef double _read_double(self, object file) - cdef int32_t _read_int32(self, object file) cdef class KDTree3D(KDTree3DCore): cdef bint _trace_leaf(self, int32_t id, Ray ray, double max_range) - cpdef bint _trace_items(self, list items, Ray ray, double max_range) - cdef list _items_containing_leaf(self, int32_t id, Point3D point) - cpdef list _items_containing_items(self, list items, Point3D point) \ No newline at end of file diff --git a/raysect/core/math/spatial/kdtree3d.pyx b/raysect/core/math/spatial/kdtree3d.pyx index e82306f4..c1a8a195 100644 --- a/raysect/core/math/spatial/kdtree3d.pyx +++ b/raysect/core/math/spatial/kdtree3d.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -40,17 +40,21 @@ from libc.stdint cimport int32_t from libc.math cimport log, ceil cimport cython -# this number of nodes will be pre-allocated when the kd-tree is initially created -DEF INITIAL_NODE_COUNT = 128 -# friendly name for first node -DEF ROOT_NODE = 0 +# constants +cdef enum: -# node types -DEF LEAF = -1 # leaf node -DEF X_AXIS = 0 # branch, x-axis split -DEF Y_AXIS = 1 # branch, y-axis split -DEF Z_AXIS = 2 # branch, z-axis split + # this number of nodes will be pre-allocated when the kd-tree is initially created + INITIAL_NODE_COUNT = 128 + + # friendly name for first node + ROOT_NODE = 0 + + # node types + LEAF = -1 # leaf node + X_AXIS = 0 # branch, x-axis split + Y_AXIS = 1 # branch, y-axis split + Z_AXIS = 2 # branch, z-axis split cdef class Item3D: diff --git a/raysect/core/math/spatial/meson.build b/raysect/core/math/spatial/meson.build new file mode 100644 index 00000000..9a65917d --- /dev/null +++ b/raysect/core/math/spatial/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/spatial' + +# source files +py_files = ['__init__.py'] +pyx_files = ['kdtree2d.pyx', 'kdtree3d.pyx'] +pxd_files = ['__init__.pxd', 'kdtree2d.pxd', 'kdtree3d.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/core/math/statsarray.pxd b/raysect/core/math/statsarray.pxd index 3075155a..3352331a 100644 --- a/raysect/core/math/statsarray.pxd +++ b/raysect/core/math/statsarray.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -40,13 +40,9 @@ cdef class StatsBin: readonly int samples cpdef object clear(self) - cpdef StatsBin copy(self) - cpdef object add_sample(self, double sample) - cpdef object combine_samples(self, double mean, double variance, int sample_count) - cpdef double error(self) @@ -62,19 +58,12 @@ cdef class StatsArray1D: int[::1] samples_mv cpdef object clear(self) - cpdef StatsArray1D copy(self) - cpdef object add_sample(self, int x, double sample) - cpdef object combine_samples(self, int x, double mean, double variance, int sample_count) - cpdef double error(self, int x) - cpdef ndarray errors(self) - cdef void _new_buffers(self) - cdef object _bounds_check(self, int x) @@ -90,19 +79,12 @@ cdef class StatsArray2D: int[:,::1] samples_mv cpdef object clear(self) - cpdef StatsArray2D copy(self) - cpdef object add_sample(self, int x, int y, double sample) - cpdef object combine_samples(self, int x, int y, double mean, double variance, int sample_count) - cpdef double error(self, int x, int y) - cpdef ndarray errors(self) - cdef void _new_buffers(self) - cdef object _bounds_check(self, int x, int y) @@ -118,17 +100,10 @@ cdef class StatsArray3D: int[:,:,::1] samples_mv cpdef object clear(self) - cpdef StatsArray3D copy(self) - cpdef object add_sample(self, int x, int y, int z, double sample) - cpdef object combine_samples(self, int x, int y, int z, double mean, double variance, int sample_count) - cpdef double error(self, int x, int y, int z) - cpdef ndarray errors(self) - cdef void _new_buffers(self) - cdef object _bounds_check(self, int x, int y, int z) diff --git a/raysect/core/math/statsarray.pyx b/raysect/core/math/statsarray.pyx index c4f5b38e..4b4a60b2 100644 --- a/raysect/core/math/statsarray.pyx +++ b/raysect/core/math/statsarray.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -52,13 +52,19 @@ cdef class StatsBin: self.samples = 0 cpdef object clear(self): - """ Erase the current statistics stored in this StatsBin. """ + """ + Erase the current statistics stored in this StatsBin. + """ + self.mean = 0.0 self.variance = 0.0 self.samples = 0 cpdef StatsBin copy(self): - """ Instantiate a new StatsBin object with the same statistical results. """ + """ + Instantiate a new StatsBin object with the same statistical results. + """ + obj = StatsBin() obj.mean = self.mean obj.variance = self.variance @@ -71,6 +77,7 @@ cdef class StatsBin: :param float sample: The sample value to be added. """ + _add_sample(sample, &self.mean, &self.variance, &self.samples) cpdef object combine_samples(self, double mean, double variance, int sample_count): @@ -115,7 +122,10 @@ cdef class StatsBin: self.samples = nt cpdef double error(self): - """ Compute the standard error of this sample distribution. """ + """ + Compute the standard error of this sample distribution. + """ + return _std_error(self.variance, self.samples) @@ -154,17 +164,25 @@ cdef class StatsArray1D: @property def shape(self): - """ The numpy style array shape of the underlying StatsArray. """ + """ + The numpy style array shape of the underlying StatsArray. + """ return (self.length, ) cpdef object clear(self): - """ Erase the current statistics stored in this StatsArray. """ + """ + Erase the current statistics stored in this StatsArray. + """ + self._new_buffers() @cython.initializedcheck(False) cpdef StatsArray1D copy(self): - """ Instantiate a new StatsArray1D object with the same statistical results. """ + """ + Instantiate a new StatsArray1D object with the same statistical results. + """ + obj = StatsArray1D(self.length) obj.mean_mv[:] = self.mean_mv[:] obj.variance_mv[:] = self.variance_mv[:] @@ -335,16 +353,25 @@ cdef class StatsArray2D: @property def shape(self): - """ The numpy style array shape of the underlying StatsArray. """ + """ + The numpy style array shape of the underlying StatsArray. + """ + return self.nx, self.ny cpdef object clear(self): - """ Erase the current statistics stored in this StatsArray. """ + """ + Erase the current statistics stored in this StatsArray. + """ + self._new_buffers() @cython.initializedcheck(False) cpdef StatsArray2D copy(self): - """ Instantiate a new StatsArray2D object with the same statistical results. """ + """ + Instantiate a new StatsArray2D object with the same statistical results. + """ + obj = StatsArray2D(self.nx, self.ny) obj.mean_mv[:] = self.mean_mv[:] obj.variance_mv[:] = self.variance_mv[:] @@ -531,18 +558,27 @@ cdef class StatsArray3D: @property def shape(self): - """ The numpy style array shape of the underlying StatsArray. """ + """ + The numpy style array shape of the underlying StatsArray. + """ + return self.nx, self.ny, self.nz cpdef object clear(self): - """ Erase the current statistics stored in this StatsArray. """ + """ + Erase the current statistics stored in this StatsArray. + """ + self._new_buffers() @cython.boundscheck(False) @cython.wraparound(False) @cython.initializedcheck(False) cpdef StatsArray3D copy(self): - """ Instantiate a new StatsArray3D object with the same statistical results. """ + """ + Instantiate a new StatsArray3D object with the same statistical results. + """ + obj = StatsArray3D(self.nx, self.ny, self.nz) obj.mean_mv[:] = self.mean_mv[:] obj.variance_mv[:] = self.variance_mv[:] diff --git a/raysect/core/math/tests/meson.build b/raysect/core/math/tests/meson.build new file mode 100644 index 00000000..909aee06 --- /dev/null +++ b/raysect/core/math/tests/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/math/tests' + +# source files +py_files = ['__init__.py', 'test_affinematrix3d.py', 'test_interaction3d.py', 'test_normal3d.py', 'test_point2d.py', 'test_point3d.py', 'test_quaternion.py', 'test_random.py', 'test_transform.py', 'test_vector2d.py', 'test_vector3d.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/core/math/tests/test_affinematrix3d.py b/raysect/core/math/tests/test_affinematrix3d.py index 43faaa63..23b28f51 100644 --- a/raysect/core/math/tests/test_affinematrix3d.py +++ b/raysect/core/math/tests/test_affinematrix3d.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/tests/test_interaction3d.py b/raysect/core/math/tests/test_interaction3d.py index 9c2105dd..108a1719 100644 --- a/raysect/core/math/tests/test_interaction3d.py +++ b/raysect/core/math/tests/test_interaction3d.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/tests/test_normal3d.py b/raysect/core/math/tests/test_normal3d.py index d791a72e..38c95ecc 100644 --- a/raysect/core/math/tests/test_normal3d.py +++ b/raysect/core/math/tests/test_normal3d.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/tests/test_point2d.py b/raysect/core/math/tests/test_point2d.py index 30d1e360..3e9d1da0 100644 --- a/raysect/core/math/tests/test_point2d.py +++ b/raysect/core/math/tests/test_point2d.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/tests/test_point3d.py b/raysect/core/math/tests/test_point3d.py index ac43f9b8..59ee2316 100644 --- a/raysect/core/math/tests/test_point3d.py +++ b/raysect/core/math/tests/test_point3d.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/tests/test_quaternion.py b/raysect/core/math/tests/test_quaternion.py index b6477a1d..ea5a4a31 100644 --- a/raysect/core/math/tests/test_quaternion.py +++ b/raysect/core/math/tests/test_quaternion.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/tests/test_random.py b/raysect/core/math/tests/test_random.py index 9ca6d7a3..bec3ce4c 100644 --- a/raysect/core/math/tests/test_random.py +++ b/raysect/core/math/tests/test_random.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/tests/test_transform.py b/raysect/core/math/tests/test_transform.py index 5efdb6af..5a9f5026 100644 --- a/raysect/core/math/tests/test_transform.py +++ b/raysect/core/math/tests/test_transform.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/tests/test_vector2d.py b/raysect/core/math/tests/test_vector2d.py index e47eea24..c6a68d9f 100644 --- a/raysect/core/math/tests/test_vector2d.py +++ b/raysect/core/math/tests/test_vector2d.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/tests/test_vector3d.py b/raysect/core/math/tests/test_vector3d.py index d4f2e9f9..d74c071c 100644 --- a/raysect/core/math/tests/test_vector3d.py +++ b/raysect/core/math/tests/test_vector3d.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/transform.pxd b/raysect/core/math/transform.pxd index b489a683..705c5dde 100644 --- a/raysect/core/math/transform.pxd +++ b/raysect/core/math/transform.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/transform.pyx b/raysect/core/math/transform.pyx index 75b5b93c..41c1cd0b 100644 --- a/raysect/core/math/transform.pyx +++ b/raysect/core/math/transform.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -29,18 +29,14 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -from libc.math cimport sin, cos, sqrt, asin, atan2, M_PI as pi +from libc.math cimport sin, cos, sqrt, asin, atan2 from raysect.core.math.affinematrix cimport new_affinematrix3d from raysect.core.math.point cimport new_point3d cimport cython -DEF RAD2DEG = 57.29577951308232000 # 180 / pi -DEF DEG2RAD = 0.017453292519943295 # pi / 180 - - -FORWARD = 'forward' -UP = 'up' +cdef const double RAD2DEG = 57.29577951308232000 # 180 / pi +cdef const double DEG2RAD = 0.017453292519943295 # pi / 180 cpdef AffineMatrix3D translate(double x, double y, double z): @@ -108,7 +104,7 @@ cpdef AffineMatrix3D rotate_x(double angle): cdef double r - r = pi * angle / 180.0 + r = DEG2RAD * angle return new_affinematrix3d(1, 0, 0, 0, 0, cos(r), -sin(r), 0, 0, sin(r), cos(r), 0, @@ -136,7 +132,7 @@ cpdef AffineMatrix3D rotate_y(double angle): cdef double r - r = pi * angle / 180.0 + r = DEG2RAD * angle return new_affinematrix3d(cos(r), 0, sin(r), 0, 0, 1, 0, 0, -sin(r), 0, cos(r), 0, @@ -164,7 +160,7 @@ cpdef AffineMatrix3D rotate_z(double angle): cdef double r - r = pi * angle / 180.0 + r = DEG2RAD * angle return new_affinematrix3d(cos(r), -sin(r), 0, 0, sin(r), cos(r), 0, 0, 0, 0, 1, 0, @@ -195,7 +191,7 @@ cpdef AffineMatrix3D rotate_vector(double angle, Vector3D v): cdef double r, s, c, ci vn = v.normalise() - r = pi * angle / 180.0 + r = DEG2RAD * angle s = sin(r) c = cos(r) ci = 1.0 - c @@ -292,16 +288,16 @@ cpdef AffineMatrix3D rotate_basis(Vector3D forward, Vector3D up): cpdef tuple to_cylindrical(Point3D point): """ - Convert the given 3D point in cartesian space to cylindrical coordinates. - + Convert the given 3D point in cartesian space to cylindrical coordinates. + :param Point3D point: The 3D point to be transformed into cylindrical coordinates. :rtype: tuple :return: A tuple of r, z, phi coordinates. - + .. code-block:: pycon - + >>> from raysect.core.math import to_cylindrical, Point3D - + >>> point = Point3D(1, 1, 1) >>> to_cylindrical(point) (1.4142135623730951, 1.0, 45.0) @@ -318,15 +314,15 @@ cpdef tuple to_cylindrical(Point3D point): cpdef Point3D from_cylindrical(double r, double z, double phi): """ Convert a 3D point in cylindrical coordinates to a point in cartesian coordinates. - + :param float r: The radial coordinate. :param float z: The z-axis height coordinate. :param float phi: The azimuthal coordinate in degrees. :rtype: Point3D :return: A Point3D in cartesian space. - + .. code-block:: pycon - + >>> from raysect.core.math import from_cylindrical >>> from_cylindrical(1, 0, 45) @@ -348,21 +344,21 @@ cpdef Point3D from_cylindrical(double r, double z, double phi): cpdef (double, double, double) extract_rotation(AffineMatrix3D m, bint z_up=False): """ Extracts the rotation component of the affine matrix. - + The yaw, pitch and roll can be extracted for two common coordinate conventions by specifying the z_axis orientation: - - forward: +ve z is forward, +ve y is up, +ve x is left + + forward: +ve z is forward, +ve y is up, +ve x is left up: +ve z is up, +ve y is left, +ve x is forward The Raysect default is z axis forward. This function can be switched - to z axis up by setting the z_up parameter to True. - + to z axis up by setting the z_up parameter to True. + The matrix must consist of only rotation and translation operations. - + :param AffineMatrix3D m: An affine matrix. - :param bint z_up: Is the z-axis pointed upwards (default=False). - :return: A tuple containing (yaw, pitch, roll). + :param bint z_up: Is the z-axis pointed upwards (default=False). + :return: A tuple containing (yaw, pitch, roll). """ cdef double yaw, pitch, roll @@ -385,11 +381,11 @@ cpdef (double, double, double) extract_rotation(AffineMatrix3D m, bint z_up=Fals cpdef (double, double, double) extract_translation(AffineMatrix3D m): """ Extracts the translation component of the affine matrix. - + The matrix must consist of only rotation and translation operations. - :param AffineMatrix3D m: An affine matrix. - :return: tuple containing the x, y and z components of the translation. + :param AffineMatrix3D m: An affine matrix. + :return: tuple containing the x, y and z components of the translation. """ return m.get_element(0, 3), m.get_element(1, 3), m.get_element(2, 3) diff --git a/raysect/core/math/units.pxd b/raysect/core/math/units.pxd index 554a4a1f..0b1b906d 100644 --- a/raysect/core/math/units.pxd +++ b/raysect/core/math/units.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/math/units.pyx b/raysect/core/math/units.pyx index 0b31f713..8488725d 100644 --- a/raysect/core/math/units.pyx +++ b/raysect/core/math/units.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,6 +31,7 @@ from libc.math cimport M_1_PI + cpdef double km(double v): """ Converts kilometers to meters. @@ -40,6 +41,7 @@ cpdef double km(double v): """ return v * 1e3 + cpdef double cm(double v): """ Converts centimeters to meters. @@ -49,6 +51,7 @@ cpdef double cm(double v): """ return v * 1e-2 + cpdef double mm(double v): """ Converts millimeters to meters. @@ -58,6 +61,7 @@ cpdef double mm(double v): """ return v * 1e-3 + cpdef double um(double v): """ Converts micrometers to meters. @@ -67,6 +71,7 @@ cpdef double um(double v): """ return v * 1e-6 + cpdef double nm(double v): """ Converts nanometers to meters. @@ -76,6 +81,7 @@ cpdef double nm(double v): """ return v * 1e-9 + cpdef double mile(double v): """ Converts miles to meters. @@ -85,6 +91,7 @@ cpdef double mile(double v): """ return v * 1609.34 + cpdef double yard(double v): """ Converts yards to meters. @@ -94,6 +101,7 @@ cpdef double yard(double v): """ return v * 0.9144 + cpdef double foot(double v): """ Converts feet to meters. @@ -103,6 +111,7 @@ cpdef double foot(double v): """ return v * 0.3048 + cpdef double inch(double v): """ Converts inches to meters. @@ -112,6 +121,7 @@ cpdef double inch(double v): """ return v * 0.0254 + cpdef double mil(double v): """ Converts mils (thousandths of an inch) to meters. @@ -121,6 +131,7 @@ cpdef double mil(double v): """ return v * 2.54e-5 + cpdef radian(double v): """ Converts radians to degrees. diff --git a/raysect/core/math/vector.pxd b/raysect/core/math/vector.pxd index c65e765c..c0843002 100644 --- a/raysect/core/math/vector.pxd +++ b/raysect/core/math/vector.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,30 +32,20 @@ from raysect.core.math._vec3 cimport _Vec3 from raysect.core.math.affinematrix cimport AffineMatrix3D + cdef class Vector3D(_Vec3): cpdef Vector3D cross(self, _Vec3 v) - cpdef Vector3D normalise(self) - cpdef Vector3D transform(self, AffineMatrix3D m) - cdef Vector3D neg(self) - cdef Vector3D add(self, _Vec3 v) - cdef Vector3D sub(self, _Vec3 v) - cdef Vector3D mul(self, double m) - cdef Vector3D div(self, double m) - cpdef Vector3D copy(self) - cpdef Vector3D orthogonal(self) - cpdef Vector3D lerp(self, Vector3D b, double t) - cpdef Vector3D slerp(self, Vector3D b, double t) @@ -80,33 +70,19 @@ cdef class Vector2D: cdef public double x, y cpdef double dot(self, Vector2D v) - cdef double get_length(self) nogil - cdef object set_length(self, double v) - cdef double get_index(self, int index) nogil - cdef void set_index(self, int index, double value) nogil - cpdef double cross(self, Vector2D v) - cpdef Vector2D normalise(self) - # cpdef Vector2D transform(self, AffineMatrix2D m): - cdef Vector2D neg(self) - cdef Vector2D add(self, Vector2D v) - cdef Vector2D sub(self, Vector2D v) - cdef Vector2D mul(self, double m) - cdef Vector3D div(self, double d) - cpdef Vector2D copy(self) - cpdef Vector2D orthogonal(self) diff --git a/raysect/core/math/vector.pyx b/raysect/core/math/vector.pyx index 08e88a90..54e294a2 100644 --- a/raysect/core/math/vector.pyx +++ b/raysect/core/math/vector.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -33,7 +33,8 @@ import numbers cimport cython from libc.math cimport sqrt, fabs, NAN, acos, cos, sin -DEF EPSILON = 1e-12 + +cdef const double EPSILON = 1e-12 cdef class Vector3D(_Vec3): @@ -68,12 +69,16 @@ cdef class Vector3D(_Vec3): self.z = z def __repr__(self): - """Returns a string representation of the Vector3D object.""" + """ + Returns a string representation of the Vector3D object. + """ return "Vector3D(" + str(self.x) + ", " + str(self.y) + ", " + str(self.z) + ")" def __richcmp__(self, object other, int op): - """Provides basic vector comparison operations.""" + """ + Provides basic vector comparison operations. + """ cdef Vector3D v @@ -85,11 +90,12 @@ cdef class Vector3D(_Vec3): return self.x == v.x and self.y == v.y and self.z == v.z elif op == 3: # __ne__() return self.x != v.x or self.y != v.y or self.z != v.z - else: - return NotImplemented + + return NotImplemented def __getitem__(self, int i): - """Returns the vector coordinates by index ([0,1,2] -> [x,y,z]). + """ + Returns the vector coordinates by index ([0,1,2] -> [x,y,z]). >>> a = Vector3D(1, 0, 0) >>> a[0] @@ -102,11 +108,12 @@ cdef class Vector3D(_Vec3): return self.y elif i == 2: return self.z - else: - raise IndexError("Index out of range [0, 2].") + + raise IndexError("Index out of range [0, 2].") def __setitem__(self, int i, double value): - """Sets the vector coordinates by index ([0,1,2] -> [x,y,z]). + """ + Sets the vector coordinates by index ([0,1,2] -> [x,y,z]). >>> a = Vector3D(1, 0, 0) >>> a[1] = 2 @@ -124,122 +131,140 @@ cdef class Vector3D(_Vec3): raise IndexError("Index out of range [0, 2].") def __iter__(self): - """Iterates over the vector coordinates (x, y, z) + """ + Iterates over the vector coordinates (x, y, z) >>> a = Vector3D(0, 1, 2) >>> x, y, z = a >>> x, y, z (0.0, 1.0, 2.0) """ + yield self.x yield self.y yield self.z def __neg__(self): - """Returns a vector with the reverse orientation (negation operator). + """ + Returns a vector with the reverse orientation (negation operator). >>> a = Vector3D(1, 0, 0) >>> -a Vector3D(-1.0, -0.0, -0.0) """ - return new_vector3d(-self.x, - -self.y, - -self.z) + return new_vector3d(-self.x, -self.y, -self.z) - def __add__(object x, object y): - """Addition operator. + def __add__(self, object y): + """ + Addition operator. >>> Vector3D(1, 0, 0) + Vector3D(0, 1, 0) Vector3D(1.0, 1.0, 0.0) """ - cdef _Vec3 vx, vy + cdef _Vec3 vy - if isinstance(x, _Vec3) and isinstance(y, _Vec3): + if isinstance(y, _Vec3): + vy = <_Vec3> y + return new_vector3d(self.x + vy.x, self.y + vy.y, self.z + vy.z) - vx = <_Vec3>x - vy = <_Vec3>y + return NotImplemented - return new_vector3d(vx.x + vy.x, - vx.y + vy.y, - vx.z + vy.z) + def __radd__(self, object x): + """ + Reverse addition operator. - else: + >>> Vector3D(1, 0, 0) + Vector3D(0, 1, 0) + Vector3D(1.0, 1.0, 0.0) + """ - return NotImplemented + return self.__add__(x) - def __sub__(object x, object y): - """Subtraction operator. + def __sub__(self, object y): + """ + Subtraction operator. >>> Vector3D(1, 0, 0) - Vector3D(0, 1, 0) Vector3D(1.0, -1.0, 0.0) """ - cdef _Vec3 vx, vy + cdef _Vec3 vy - if isinstance(x, _Vec3) and isinstance(y, _Vec3): + if isinstance(y, _Vec3): + vy = <_Vec3> y + return new_vector3d(self.x - vy.x, self.y - vy.y, self.z - vy.z) - vx = <_Vec3>x - vy = <_Vec3>y + return NotImplemented - return new_vector3d(vx.x - vy.x, - vx.y - vy.y, - vx.z - vy.z) + def __rsub__(self, object x): + """ + Reverse subtraction operator. - else: + >>> Vector3D(1, 0, 0) - Vector3D(0, 1, 0) + Vector3D(1.0, -1.0, 0.0) + """ - return NotImplemented + cdef _Vec3 vx - def __mul__(object x, object y): - """Multiplication operator. + if isinstance(x, _Vec3): + vx = <_Vec3> x + return new_vector3d(vx.x - self.x, vx.y - self.y, vx.z - self.z) + + return NotImplemented + + def __mul__(self, object y): + """ + Multiplication operator. 3D vectors can be multiplied with both scalars and transformation matrices. >>> from raysect.core import Vector3D, rotate_x - >>> 2 * Vector3D(1, 2, 3) + >>> Vector3D(1, 2, 3) * 2 Vector3D(2.0, 4.0, 6.0) - >>> rotate_x(90) * Vector3D(0, 0, 1) - Vector3D(0.0, -1.0, 0.0) """ cdef double s - cdef Vector3D v cdef AffineMatrix3D m - if isinstance(x, numbers.Real) and isinstance(y, Vector3D): - - s = x - v = y + if isinstance(y, numbers.Real): + s = y + return new_vector3d(s * self.x, s * self.y, s * self.z) - return new_vector3d(s * v.x, - s * v.y, - s * v.z) + return NotImplemented - elif isinstance(x, Vector3D) and isinstance(y, numbers.Real): - - s = y - v = x + def __rmul__(self, object x): + """ + Reverse multiplication operator. - return new_vector3d(s * v.x, - s * v.y, - s * v.z) + 3D vectors can be multiplied with both scalars and transformation matrices. - elif isinstance(x, AffineMatrix3D) and isinstance(y, Vector3D): + >>> from raysect.core import Vector3D, rotate_x + >>> 2 * Vector3D(1, 2, 3) + Vector3D(2.0, 4.0, 6.0) + >>> rotate_x(90) * Vector3D(0, 0, 1) + Vector3D(0.0, -1.0, 0.0) + """ - m = x - v = y + cdef double s + cdef AffineMatrix3D m - return new_vector3d(m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z, - m.m[1][0] * v.x + m.m[1][1] * v.y + m.m[1][2] * v.z, - m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z) + if isinstance(x, numbers.Real): + s = x + return new_vector3d(s * self.x, s * self.y, s * self.z) - else: + elif isinstance(x, AffineMatrix3D): + m = x + return new_vector3d( + m.m[0][0] * self.x + m.m[0][1] * self.y + m.m[0][2] * self.z, + m.m[1][0] * self.x + m.m[1][1] * self.y + m.m[1][2] * self.z, + m.m[2][0] * self.x + m.m[2][1] * self.y + m.m[2][2] * self.z + ) - return NotImplemented + return NotImplemented @cython.cdivision(True) - def __truediv__(object x, object y): + def __truediv__(self, object y): """Division operator. >>> Vector3D(1, 1, 1) / 2 @@ -247,27 +272,19 @@ cdef class Vector3D(_Vec3): """ cdef double d - cdef Vector3D v - if isinstance(x, Vector3D) and isinstance(y, numbers.Real): + if isinstance(y, numbers.Real): d = y # prevent divide my zero if d == 0.0: - raise ZeroDivisionError("Cannot divide a vector by a zero scalar.") - v = x d = 1.0 / d + return new_vector3d(d * self.x, d * self.y, d * self.z) - return new_vector3d(d * v.x, - d * v.y, - d * v.z) - - else: - - raise TypeError("Unsupported operand type. Expects a real number.") + raise TypeError("Unsupported operand type. Expects a real number.") cpdef Vector3D cross(self, _Vec3 v): """ @@ -286,9 +303,11 @@ cdef class Vector3D(_Vec3): Vector3D(0.0, 0.0, 1.0) """ - return new_vector3d(self.y * v.z - v.y * self.z, - self.z * v.x - v.z * self.x, - self.x * v.y - v.x * self.y) + return new_vector3d( + self.y * v.z - v.y * self.z, + self.z * v.x - v.z * self.x, + self.x * v.y - v.x * self.y + ) @cython.cdivision(True) cpdef Vector3D normalise(self): @@ -311,15 +330,11 @@ cdef class Vector3D(_Vec3): # if current length is zero, problem is ill defined t = self.x * self.x + self.y * self.y + self.z * self.z if t == 0.0: - raise ZeroDivisionError("A zero length vector can not be normalised as the direction of a zero length vector is undefined.") # normalise and rescale vector t = 1.0 / sqrt(t) - - return new_vector3d(self.x * t, - self.y * t, - self.z * t) + return new_vector3d(self.x * t, self.y * t, self.z * t) cpdef Vector3D transform(self, AffineMatrix3D m): """ @@ -347,9 +362,11 @@ cdef class Vector3D(_Vec3): Vector3D(0.0, -1.0, 6.123233995736766e-17) """ - return new_vector3d(m.m[0][0] * self.x + m.m[0][1] * self.y + m.m[0][2] * self.z, - m.m[1][0] * self.x + m.m[1][1] * self.y + m.m[1][2] * self.z, - m.m[2][0] * self.x + m.m[2][1] * self.y + m.m[2][2] * self.z) + return new_vector3d( + m.m[0][0] * self.x + m.m[0][1] * self.y + m.m[0][2] * self.z, + m.m[1][0] * self.x + m.m[1][1] * self.y + m.m[1][2] * self.z, + m.m[2][0] * self.x + m.m[2][1] * self.y + m.m[2][2] * self.z + ) cdef Vector3D neg(self): """ @@ -359,9 +376,7 @@ cdef class Vector3D(_Vec3): to the equivalent python operator. """ - return new_vector3d(-self.x, - -self.y, - -self.z) + return new_vector3d(-self.x, -self.y, -self.z) cdef Vector3D add(self, _Vec3 v): """ @@ -371,9 +386,7 @@ cdef class Vector3D(_Vec3): to the equivalent python operator. """ - return new_vector3d(self.x + v.x, - self.y + v.y, - self.z + v.z) + return new_vector3d(self.x + v.x, self.y + v.y, self.z + v.z) cdef Vector3D sub(self, _Vec3 v): """ @@ -383,9 +396,7 @@ cdef class Vector3D(_Vec3): to the equivalent python operator. """ - return new_vector3d(self.x - v.x, - self.y - v.y, - self.z - v.z) + return new_vector3d(self.x - v.x, self.y - v.y, self.z - v.z) cdef Vector3D mul(self, double m): """ @@ -395,9 +406,7 @@ cdef class Vector3D(_Vec3): to the equivalent python operator. """ - return new_vector3d(self.x * m, - self.y * m, - self.z * m) + return new_vector3d(self.x * m, self.y * m, self.z * m) @cython.cdivision(True) cdef Vector3D div(self, double d): @@ -409,14 +418,10 @@ cdef class Vector3D(_Vec3): """ if d == 0.0: - raise ZeroDivisionError("Cannot divide a vector by a zero scalar.") d = 1.0 / d - - return new_vector3d(self.x * d, - self.y * d, - self.z * d) + return new_vector3d(self.x * d, self.y * d, self.z * d) cpdef Vector3D copy(self): """ @@ -431,9 +436,7 @@ cdef class Vector3D(_Vec3): Vector3D(1.0, 1.0, 1.0) """ - return new_vector3d(self.x, - self.y, - self.z) + return new_vector3d(self.x, self.y, self.z) # todo: this is common code with normal, move into math.cython and call cpdef Vector3D orthogonal(self): @@ -493,7 +496,6 @@ cdef class Vector3D(_Vec3): raise ValueError("Vector lerp parameter t must be in range (0, 1).") t_minus = 1 - t - return new_vector3d(self.x * t_minus + b.x * t, self.y * t_minus + b.y * t, self.z * t_minus + b.z * t) cpdef Vector3D slerp(self, Vector3D b, double t): @@ -631,12 +633,16 @@ cdef class Vector2D: self.y = y def __repr__(self): - """Returns a string representation of the Vector2D object.""" + """ + Returns a string representation of the Vector2D object. + """ return "Vector2D(" + str(self.x) + ", " + str(self.y) + ")" def __richcmp__(self, object other, int op): - """Provides basic vector comparison operations.""" + """ + Provides basic vector comparison operations. + """ cdef Vector2D v @@ -648,11 +654,12 @@ cdef class Vector2D: return self.x == v.x and self.y == v.y elif op == 3: # __ne__() return self.x != v.x or self.y != v.y - else: - return NotImplemented + + return NotImplemented def __getitem__(self, int i): - """Returns the vector coordinates by index ([0,1] -> [x,y]). + """ + Returns the vector coordinates by index ([0,1] -> [x,y]). >>> a = Vector2D(1, 0) >>> a[0] @@ -663,11 +670,12 @@ cdef class Vector2D: return self.x elif i == 1: return self.y - else: - raise IndexError("Index out of range [0, 1].") + + raise IndexError("Index out of range [0, 1].") def __setitem__(self, int i, double value): - """Sets the vector coordinates by index ([0,1] -> [x,y]). + """ + Sets the vector coordinates by index ([0,1] -> [x,y]). >>> a = Vector2D(1, 0) >>> a[1] = 2 @@ -683,7 +691,8 @@ cdef class Vector2D: raise IndexError("Index out of range [0, 1].") def __iter__(self): - """Iterates over the vector coordinates (x, y) + """ + Iterates over the vector coordinates (x, y) >>> a = Vector2D(1, 0) >>> x, y = a @@ -691,11 +700,13 @@ cdef class Vector2D: (1.0, 0.0) """ + yield self.x yield self.y def __neg__(self): - """Returns a vector with the reverse orientation (negation operator). + """ + Returns a vector with the reverse orientation (negation operator). >>> a = Vector2D(1, 0) >>> -a @@ -705,113 +716,93 @@ cdef class Vector2D: return new_vector2d(-self.x, -self.y) - def __add__(object x, object y): - """Addition operator. + def __add__(self, object y): + """ + Addition operator. >>> Vector2D(1, 0) + Vector2D(0, 1) Vector2D(1.0, 1.0) """ - cdef Vector2D vx, vy - - if isinstance(x, Vector2D) and isinstance(y, Vector2D): + cdef Vector2D vy - vx = x + if isinstance(y, Vector2D): vy = y + return new_vector2d(self.x + vy.x, self.y + vy.y) - return new_vector2d(vx.x + vy.x, vx.y + vy.y) - - else: - - return NotImplemented + return NotImplemented - def __sub__(object x, object y): - """Subtraction operator. + def __sub__(self, object y): + """ + Subtraction operator. >>> Vector2D(1, 0) - Vector2D(0, 1) Vector2D(1.0, -1.0) """ - cdef Vector2D vx, vy - - if isinstance(x, Vector2D) and isinstance(y, Vector2D): + cdef Vector2D vy - vx = x + if isinstance(y, Vector2D): vy = y + return new_vector2d(self.x - vy.x, self.y - vy.y) - return new_vector2d(vx.x - vy.x, vx.y - vy.y) - - else: + return NotImplemented - return NotImplemented - - # TODO - add 2D affine transformations - def __mul__(object x, object y): - """Multiplication operator. + def __mul__(self, object y): + """ + Multiplication operator. - >>> 2 * Vector3D(1, 2) + >>> Vector3D(1, 2) * 2 Vector2D(2.0, 4.0) """ cdef double s - cdef Vector2D v - # cdef AffineMatrix2D m - - if isinstance(x, numbers.Real) and isinstance(y, Vector2D): - - s = x - v = y - return new_vector2d(s * v.x, s * v.y,) + if isinstance(y, numbers.Real): + s = y + return new_vector2d(s * self.x, s * self.y) - elif isinstance(x, Vector2D) and isinstance(y, numbers.Real): + raise TypeError("Unsupported operand type. Expects a real number.") - s = y - v = x + def __rmul__(self, object x): + """ + Reverse multiplication operator. - return new_vector2d(s * v.x, s * v.y) + >>> 2 * Vector3D(1, 2) + Vector2D(2.0, 4.0) + """ - # elif isinstance(x, AffineMatrix3D) and isinstance(y, Vector3D): - # - # m = x - # v = y - # - # return new_vector3d(m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z, - # m.m[1][0] * v.x + m.m[1][1] * v.y + m.m[1][2] * v.z, - # m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z) + cdef double s - else: + if isinstance(x, numbers.Real): + s = x + return new_vector2d(s * self.x, s * self.y) - return NotImplemented + raise TypeError("Unsupported operand type. Expects a real number.") @cython.cdivision(True) - def __truediv__(object x, object y): - """Division operator. + def __truediv__(self, object y): + """ + Division operator. >>> Vector2D(1, 1) / 2 Vector2D(0.5, 0.5) """ cdef double d - cdef Vector2D v - if isinstance(x, Vector2D) and isinstance(y, numbers.Real): + if isinstance(y, numbers.Real): d = y # prevent divide my zero if d == 0.0: - raise ZeroDivisionError("Cannot divide a vector by a zero scalar.") - v = x d = 1.0 / d + return new_vector2d(d * self.x, d * self.y) - return new_vector2d(d * v.x, d * v.y) - - else: - - raise TypeError("Unsupported operand type. Expects a real number.") + raise TypeError("Unsupported operand type. Expects a real number.") @property def length(self): @@ -827,6 +818,7 @@ cdef class Vector2D: 1.4142135623730951 """ + return self.get_length() @length.setter @@ -880,7 +872,6 @@ cdef class Vector2D: # normalise and rescale vector t = v / sqrt(t) - self.x = self.x * t self.y = self.y * t @@ -897,8 +888,8 @@ cdef class Vector2D: return self.x elif index == 1: return self.y - else: - return NAN + + return NAN cdef void set_index(self, int index, double value) nogil: """ @@ -959,7 +950,6 @@ cdef class Vector2D: # if current length is zero, problem is ill defined t = self.x * self.x + self.y * self.y if t == 0.0: - raise ZeroDivisionError("A zero length vector can not be normalised as the direction of a zero length vector is undefined.") # normalise and rescale vector @@ -1036,11 +1026,9 @@ cdef class Vector2D: """ if d == 0.0: - raise ZeroDivisionError("Cannot divide a vector by a zero scalar.") d = 1.0 / d - return new_vector2d(self.x * d, self.y * d) cpdef Vector2D copy(self): @@ -1073,11 +1061,7 @@ cdef class Vector2D: """ - cdef: - Vector2D n - - n = self.normalise() - + cdef Vector2D n = self.normalise() return new_vector2d(-n.y, n.x) diff --git a/raysect/core/meson.build b/raysect/core/meson.build new file mode 100644 index 00000000..ab291f7a --- /dev/null +++ b/raysect/core/meson.build @@ -0,0 +1,33 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core' + +# source files +py_files = ['__init__.py', 'constants.py', 'workflow.py'] +pyx_files = ['boundingbox.pyx', 'boundingsphere.pyx', 'containers.pyx', 'intersection.pyx', 'material.pyx', 'ray.pyx'] +pxd_files = ['__init__.pxd', 'boundingbox.pxd', 'boundingsphere.pxd', 'containers.pxd', 'intersection.pxd', 'material.pxd', 'ray.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('acceleration') +subdir('math') +subdir('scenegraph') +subdir('tests') diff --git a/raysect/core/ray.pxd b/raysect/core/ray.pxd index afdf07a2..4e02656b 100644 --- a/raysect/core/ray.pxd +++ b/raysect/core/ray.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -39,7 +39,6 @@ cdef class Ray: cdef public double max_distance cpdef Point3D point_on(self, double t) - cpdef Ray copy(self, Point3D origin=*, Vector3D direction=*) diff --git a/raysect/core/ray.pyx b/raysect/core/ray.pyx index 15d97910..e0549923 100644 --- a/raysect/core/ray.pyx +++ b/raysect/core/ray.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -29,12 +29,10 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +from libc.math cimport INFINITY from raysect.core.math cimport new_point3d cimport cython -# cython doesn't have a built-in infinity constant, this compiles to +infinity -DEF INFINITY = 1e999 - @cython.freelist(256) cdef class Ray: diff --git a/raysect/core/scenegraph/__init__.pxd b/raysect/core/scenegraph/__init__.pxd index 6a37263c..b6840cda 100644 --- a/raysect/core/scenegraph/__init__.pxd +++ b/raysect/core/scenegraph/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/scenegraph/_nodebase.pxd b/raysect/core/scenegraph/_nodebase.pxd index 76503a55..159c0fe6 100644 --- a/raysect/core/scenegraph/_nodebase.pxd +++ b/raysect/core/scenegraph/_nodebase.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/scenegraph/_nodebase.pyx b/raysect/core/scenegraph/_nodebase.pyx index 0a9032d6..726b4b5e 100644 --- a/raysect/core/scenegraph/_nodebase.pyx +++ b/raysect/core/scenegraph/_nodebase.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/scenegraph/meson.build b/raysect/core/scenegraph/meson.build new file mode 100644 index 00000000..9e6c2398 --- /dev/null +++ b/raysect/core/scenegraph/meson.build @@ -0,0 +1,30 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/scenegraph' + +# source files +py_files = ['__init__.py'] +pyx_files = ['_nodebase.pyx', 'node.pyx', 'observer.pyx', 'primitive.pyx', 'signal.pyx', 'utility.pyx', 'world.pyx'] +pxd_files = ['__init__.pxd', '_nodebase.pxd', 'node.pxd', 'observer.pxd', 'primitive.pxd', 'signal.pxd', 'utility.pxd', 'world.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('tests') diff --git a/raysect/core/scenegraph/node.pxd b/raysect/core/scenegraph/node.pxd index bdeff42a..e0350249 100644 --- a/raysect/core/scenegraph/node.pxd +++ b/raysect/core/scenegraph/node.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,10 +32,9 @@ from raysect.core.scenegraph._nodebase cimport _NodeBase from raysect.core.math.affinematrix cimport AffineMatrix3D + cdef class Node(_NodeBase): cpdef AffineMatrix3D to(self, _NodeBase node) - cpdef AffineMatrix3D to_local(self) - cpdef AffineMatrix3D to_root(self) diff --git a/raysect/core/scenegraph/node.pyx b/raysect/core/scenegraph/node.pyx index 61ed6e79..70a05cbf 100644 --- a/raysect/core/scenegraph/node.pyx +++ b/raysect/core/scenegraph/node.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/scenegraph/observer.pxd b/raysect/core/scenegraph/observer.pxd index f4ef9e62..0fdde98e 100644 --- a/raysect/core/scenegraph/observer.pxd +++ b/raysect/core/scenegraph/observer.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,6 +31,7 @@ from raysect.core.scenegraph.node cimport Node + cdef class Observer(Node): cpdef observe(self) \ No newline at end of file diff --git a/raysect/core/scenegraph/observer.pyx b/raysect/core/scenegraph/observer.pyx index ff16a50b..1d56a45a 100644 --- a/raysect/core/scenegraph/observer.pyx +++ b/raysect/core/scenegraph/observer.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/scenegraph/primitive.pxd b/raysect/core/scenegraph/primitive.pxd index db5e6d3a..52f46b9a 100644 --- a/raysect/core/scenegraph/primitive.pxd +++ b/raysect/core/scenegraph/primitive.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -44,19 +44,11 @@ cdef class Primitive(Node): cdef Material _material cdef Material get_material(self) - cpdef Intersection hit(self, Ray ray) - cpdef Intersection next_intersection(self) - cpdef bint contains(self, Point3D p) except -1 - cpdef BoundingBox3D bounding_box(self) - cpdef BoundingSphere3D bounding_sphere(self) - cpdef object instance(self, object parent=*, AffineMatrix3D transform=*, Material material=*, str name=*) - cpdef object notify_geometry_change(self) - - cpdef object notify_material_change(self) \ No newline at end of file + cpdef object notify_material_change(self) diff --git a/raysect/core/scenegraph/primitive.pyx b/raysect/core/scenegraph/primitive.pyx index b4a1addd..22d78f04 100644 --- a/raysect/core/scenegraph/primitive.pyx +++ b/raysect/core/scenegraph/primitive.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/scenegraph/signal.pxd b/raysect/core/scenegraph/signal.pxd index 8a8c7bc0..0c6a43b8 100644 --- a/raysect/core/scenegraph/signal.pxd +++ b/raysect/core/scenegraph/signal.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/scenegraph/signal.pyx b/raysect/core/scenegraph/signal.pyx index 43e0d4ff..a52ca56b 100644 --- a/raysect/core/scenegraph/signal.pyx +++ b/raysect/core/scenegraph/signal.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/scenegraph/tests/meson.build b/raysect/core/scenegraph/tests/meson.build new file mode 100644 index 00000000..1841bdc7 --- /dev/null +++ b/raysect/core/scenegraph/tests/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/scenegraph/tests' + +# source files +py_files = ['__init__.py', 'test_node.py', 'test_observer.py', 'test_primitive.py', 'test_world.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/core/scenegraph/tests/test_node.py b/raysect/core/scenegraph/tests/test_node.py index 6e4eaf43..6a036685 100644 --- a/raysect/core/scenegraph/tests/test_node.py +++ b/raysect/core/scenegraph/tests/test_node.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/scenegraph/tests/test_observer.py b/raysect/core/scenegraph/tests/test_observer.py index c6c99f00..ffa1debd 100644 --- a/raysect/core/scenegraph/tests/test_observer.py +++ b/raysect/core/scenegraph/tests/test_observer.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/scenegraph/tests/test_primitive.py b/raysect/core/scenegraph/tests/test_primitive.py index 96619fde..25491b74 100644 --- a/raysect/core/scenegraph/tests/test_primitive.py +++ b/raysect/core/scenegraph/tests/test_primitive.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/scenegraph/tests/test_world.py b/raysect/core/scenegraph/tests/test_world.py index 44005a20..9ddcdda3 100644 --- a/raysect/core/scenegraph/tests/test_world.py +++ b/raysect/core/scenegraph/tests/test_world.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/scenegraph/utility.pxd b/raysect/core/scenegraph/utility.pxd index 9583b803..6b3b452f 100644 --- a/raysect/core/scenegraph/utility.pxd +++ b/raysect/core/scenegraph/utility.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/scenegraph/utility.pyx b/raysect/core/scenegraph/utility.pyx index aa99a2ea..0870aa3d 100644 --- a/raysect/core/scenegraph/utility.pyx +++ b/raysect/core/scenegraph/utility.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -35,6 +35,7 @@ from raysect.core.scenegraph._nodebase cimport _NodeBase from raysect.core.scenegraph.node cimport Node from raysect.core.scenegraph.signal cimport ChangeSignal + cdef class BridgeNode(Node): """ Specialised scene-graph root node that propagates geometry notifications. diff --git a/raysect/core/scenegraph/world.pxd b/raysect/core/scenegraph/world.pxd index 5c162d1a..57068045 100644 --- a/raysect/core/scenegraph/world.pxd +++ b/raysect/core/scenegraph/world.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -35,18 +35,17 @@ from raysect.core.acceleration.accelerator cimport Accelerator from raysect.core.math cimport Point3D, AffineMatrix3D from raysect.core.scenegraph._nodebase cimport _NodeBase + cdef class World(_NodeBase): - cdef bint _rebuild_accelerator - cdef Accelerator _accelerator - cdef list _primitives - cdef list _observers + cdef: + bint _rebuild_accelerator + Accelerator _accelerator + list _primitives + list _observers cpdef AffineMatrix3D to(self, _NodeBase node) - cpdef Intersection hit(self, Ray ray) - cpdef list contains(self, Point3D point) - cpdef build_accelerator(self, bint force=*) diff --git a/raysect/core/scenegraph/world.pyx b/raysect/core/scenegraph/world.pyx index d25db0a5..d44de0a6 100644 --- a/raysect/core/scenegraph/world.pyx +++ b/raysect/core/scenegraph/world.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/core/tests/meson.build b/raysect/core/tests/meson.build new file mode 100644 index 00000000..088244d9 --- /dev/null +++ b/raysect/core/tests/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/core/tests' + +# source files +py_files = ['__init__.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/core/workflow.py b/raysect/core/workflow.py index beedff2a..859d9123 100644 --- a/raysect/core/workflow.py +++ b/raysect/core/workflow.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/meson.build b/raysect/meson.build new file mode 100644 index 00000000..eb654f3a --- /dev/null +++ b/raysect/meson.build @@ -0,0 +1,32 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect' + +# source files +py_files = ['__init__.py', '_version.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('core') +subdir('optical') +subdir('primitive') diff --git a/raysect/optical/__init__.pxd b/raysect/optical/__init__.pxd index 3ad82713..1937e255 100644 --- a/raysect/optical/__init__.pxd +++ b/raysect/optical/__init__.pxd @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/__init__.py b/raysect/optical/__init__.py index 85d5c250..d7d3c988 100644 --- a/raysect/optical/__init__.py +++ b/raysect/optical/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/colour.pxd b/raysect/optical/colour.pxd index 15130a5d..d0211e8a 100644 --- a/raysect/optical/colour.pxd +++ b/raysect/optical/colour.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/colour.pyx b/raysect/optical/colour.pyx index f3afaff7..bedef460 100644 --- a/raysect/optical/colour.pyx +++ b/raysect/optical/colour.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/library/components/meson.build b/raysect/optical/library/components/meson.build new file mode 100644 index 00000000..a18e3e4b --- /dev/null +++ b/raysect/optical/library/components/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/library/components' + +# source files +py_files = ['__init__.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/optical/library/glass/data/meson.build b/raysect/optical/library/glass/data/meson.build new file mode 100644 index 00000000..86466f27 --- /dev/null +++ b/raysect/optical/library/glass/data/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/library/glass/data' + +# source files +py_files = [] +pyx_files = [] +pxd_files = [] +data_files = ['schott_catalog_2000.csv', 'schott_catalog_2000_full.csv'] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/optical/library/glass/meson.build b/raysect/optical/library/glass/meson.build new file mode 100644 index 00000000..112e09c0 --- /dev/null +++ b/raysect/optical/library/glass/meson.build @@ -0,0 +1,30 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/library/glass' + +# source files +py_files = ['__init__.py', 'schott.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('data') diff --git a/raysect/optical/library/glass/schott.py b/raysect/optical/library/glass/schott.py index 0582101e..e8ebbd8c 100644 --- a/raysect/optical/library/glass/schott.py +++ b/raysect/optical/library/glass/schott.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/library/meson.build b/raysect/optical/library/meson.build new file mode 100644 index 00000000..8f1ad274 --- /dev/null +++ b/raysect/optical/library/meson.build @@ -0,0 +1,33 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/library' + +# source files +py_files = ['__init__.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('components') +subdir('glass') +subdir('metal') +subdir('spectra') diff --git a/raysect/optical/library/metal/data/meson.build b/raysect/optical/library/metal/data/meson.build new file mode 100644 index 00000000..76d54742 --- /dev/null +++ b/raysect/optical/library/metal/data/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/library/metal/data' + +# source files +py_files = ['convert_data.py'] +pyx_files = [] +pxd_files = [] +data_files = ['aluminium.json', 'beryllium.json', 'cobolt.json', 'copper.json', 'gold.json', 'iron.json', 'lithium.json', 'magnesium.json', 'manganese.json', 'mercury.json', 'nickel.json', 'palladium.json', 'platinum.json', 'silicon.json', 'silver.json', 'sodium.json', 'titanium.json', 'tungsten.json'] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/optical/library/metal/meson.build b/raysect/optical/library/metal/meson.build new file mode 100644 index 00000000..fc4f84dc --- /dev/null +++ b/raysect/optical/library/metal/meson.build @@ -0,0 +1,30 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/library/metal' + +# source files +py_files = ['__init__.py', 'metal.py', 'roughmetal.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('data') diff --git a/raysect/optical/library/metal/metal.py b/raysect/optical/library/metal/metal.py index 90e47411..6a07295f 100644 --- a/raysect/optical/library/metal/metal.py +++ b/raysect/optical/library/metal/metal.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/library/metal/roughmetal.py b/raysect/optical/library/metal/roughmetal.py index 6b567a47..37837cdd 100644 --- a/raysect/optical/library/metal/roughmetal.py +++ b/raysect/optical/library/metal/roughmetal.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/library/spectra/blackbody.pyx b/raysect/optical/library/spectra/blackbody.pyx index 94d7ae3b..0e8b2d23 100644 --- a/raysect/optical/library/spectra/blackbody.pyx +++ b/raysect/optical/library/spectra/blackbody.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/library/spectra/colours.py b/raysect/optical/library/spectra/colours.py index 52c73328..dfb96e66 100644 --- a/raysect/optical/library/spectra/colours.py +++ b/raysect/optical/library/spectra/colours.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/library/spectra/meson.build b/raysect/optical/library/spectra/meson.build new file mode 100644 index 00000000..b1580737 --- /dev/null +++ b/raysect/optical/library/spectra/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/library/spectra' + +# source files +py_files = ['__init__.py', 'colours.py'] +pyx_files = ['blackbody.pyx'] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/optical/loggingray.pyx b/raysect/optical/loggingray.pyx index 5fa38d5b..71334121 100644 --- a/raysect/optical/loggingray.pyx +++ b/raysect/optical/loggingray.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -29,6 +29,8 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +from libc.math cimport INFINITY + from raysect.core cimport Intersection, Point3D, Vector3D from raysect.core.math.random cimport probability @@ -39,9 +41,6 @@ from raysect.optical.material.material cimport Material cimport cython -# cython doesn't have a built-in infinity constant, this compiles to +infinity -DEF INFINITY = 1e999 - cdef class LoggingRay(Ray): diff --git a/raysect/optical/material/__init__.pxd b/raysect/optical/material/__init__.pxd index 3a117d2e..cd4c5bcd 100644 --- a/raysect/optical/material/__init__.pxd +++ b/raysect/optical/material/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/__init__.py b/raysect/optical/material/__init__.py index c843b58d..20da1c8c 100644 --- a/raysect/optical/material/__init__.py +++ b/raysect/optical/material/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/absorber.pxd b/raysect/optical/material/absorber.pxd index 28688fe6..36abe6b5 100644 --- a/raysect/optical/material/absorber.pxd +++ b/raysect/optical/material/absorber.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/absorber.pyx b/raysect/optical/material/absorber.pyx index 2024a7f1..f9f1be2d 100644 --- a/raysect/optical/material/absorber.pyx +++ b/raysect/optical/material/absorber.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/conductor.pxd b/raysect/optical/material/conductor.pxd index 90814267..9eb5aecb 100644 --- a/raysect/optical/material/conductor.pxd +++ b/raysect/optical/material/conductor.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -51,11 +51,7 @@ cdef class RoughConductor(ContinuousBSDF): double _roughness cdef double _d(self, Vector3D s_half) - cdef double _g(self, Vector3D s_incoming, Vector3D s_outgoing) - cdef double _g1(self, Vector3D v) - cdef Spectrum _f(self, Spectrum spectrum, Vector3D s_outgoing, Vector3D s_normal) - cdef double _fresnel_conductor(self, double ci, double n, double k) nogil diff --git a/raysect/optical/material/conductor.pyx b/raysect/optical/material/conductor.pyx index 79fc4365..aa7a6222 100644 --- a/raysect/optical/material/conductor.pyx +++ b/raysect/optical/material/conductor.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/debug.pxd b/raysect/optical/material/debug.pxd index 69b05bea..0ec21e36 100644 --- a/raysect/optical/material/debug.pxd +++ b/raysect/optical/material/debug.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -42,5 +42,4 @@ cdef class Light(NullVolume): cdef class PerfectReflectingSurface(Material): - pass diff --git a/raysect/optical/material/debug.pyx b/raysect/optical/material/debug.pyx index 1a4f1610..edeb211f 100644 --- a/raysect/optical/material/debug.pyx +++ b/raysect/optical/material/debug.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/dielectric.pxd b/raysect/optical/material/dielectric.pxd index 8ec2a331..969e18b5 100644 --- a/raysect/optical/material/dielectric.pxd +++ b/raysect/optical/material/dielectric.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,6 +32,7 @@ from raysect.optical cimport SpectralFunction, NumericallyIntegratedSF from raysect.optical.material cimport Material + cdef class Sellmeier(NumericallyIntegratedSF): cdef: diff --git a/raysect/optical/material/dielectric.pyx b/raysect/optical/material/dielectric.pyx index 0e1e2cc6..b2c65ac3 100644 --- a/raysect/optical/material/dielectric.pyx +++ b/raysect/optical/material/dielectric.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/emitter/__init__.pxd b/raysect/optical/material/emitter/__init__.pxd index ce84be6e..4e670feb 100644 --- a/raysect/optical/material/emitter/__init__.pxd +++ b/raysect/optical/material/emitter/__init__.pxd @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/emitter/__init__.py b/raysect/optical/material/emitter/__init__.py index 3801bcfd..4711fb61 100644 --- a/raysect/optical/material/emitter/__init__.py +++ b/raysect/optical/material/emitter/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/emitter/anisotropic.pxd b/raysect/optical/material/emitter/anisotropic.pxd index a837c9b9..fd4a58c4 100644 --- a/raysect/optical/material/emitter/anisotropic.pxd +++ b/raysect/optical/material/emitter/anisotropic.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/emitter/anisotropic.pyx b/raysect/optical/material/emitter/anisotropic.pyx index e6fe6d42..4bd4cacc 100644 --- a/raysect/optical/material/emitter/anisotropic.pyx +++ b/raysect/optical/material/emitter/anisotropic.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/emitter/checkerboard.pxd b/raysect/optical/material/emitter/checkerboard.pxd index 40760f70..96357aa3 100644 --- a/raysect/optical/material/emitter/checkerboard.pxd +++ b/raysect/optical/material/emitter/checkerboard.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/emitter/checkerboard.pyx b/raysect/optical/material/emitter/checkerboard.pyx index 998bb12d..667b3024 100644 --- a/raysect/optical/material/emitter/checkerboard.pyx +++ b/raysect/optical/material/emitter/checkerboard.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/emitter/homogeneous.pxd b/raysect/optical/material/emitter/homogeneous.pxd index 70373bf3..2016ffeb 100644 --- a/raysect/optical/material/emitter/homogeneous.pxd +++ b/raysect/optical/material/emitter/homogeneous.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/emitter/homogeneous.pyx b/raysect/optical/material/emitter/homogeneous.pyx index bbf4647a..592037a1 100644 --- a/raysect/optical/material/emitter/homogeneous.pyx +++ b/raysect/optical/material/emitter/homogeneous.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/emitter/inhomogeneous.pxd b/raysect/optical/material/emitter/inhomogeneous.pxd index 969906fe..7db353db 100644 --- a/raysect/optical/material/emitter/inhomogeneous.pxd +++ b/raysect/optical/material/emitter/inhomogeneous.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/emitter/inhomogeneous.pyx b/raysect/optical/material/emitter/inhomogeneous.pyx index d4fb8fb6..28d9f20a 100644 --- a/raysect/optical/material/emitter/inhomogeneous.pyx +++ b/raysect/optical/material/emitter/inhomogeneous.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/emitter/meson.build b/raysect/optical/material/emitter/meson.build new file mode 100644 index 00000000..eef6b74e --- /dev/null +++ b/raysect/optical/material/emitter/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/material/emitter' + +# source files +py_files = ['__init__.py'] +pyx_files = ['anisotropic.pyx', 'checkerboard.pyx', 'homogeneous.pyx', 'inhomogeneous.pyx', 'uniform.pyx', 'unity.pyx'] +pxd_files = ['__init__.pxd', 'anisotropic.pxd', 'checkerboard.pxd', 'homogeneous.pxd', 'inhomogeneous.pxd', 'uniform.pxd', 'unity.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/optical/material/emitter/uniform.pxd b/raysect/optical/material/emitter/uniform.pxd index 559188f7..6052ab02 100644 --- a/raysect/optical/material/emitter/uniform.pxd +++ b/raysect/optical/material/emitter/uniform.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/emitter/uniform.pyx b/raysect/optical/material/emitter/uniform.pyx index 3d9b918f..bddda8af 100644 --- a/raysect/optical/material/emitter/uniform.pyx +++ b/raysect/optical/material/emitter/uniform.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/emitter/unity.pxd b/raysect/optical/material/emitter/unity.pxd index f5259484..33e20a9c 100644 --- a/raysect/optical/material/emitter/unity.pxd +++ b/raysect/optical/material/emitter/unity.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -29,7 +29,6 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -from raysect.optical cimport World, Primitive, Ray, Spectrum, Point3D, Vector3D, Normal3D, AffineMatrix3D, Intersection from raysect.optical.material.emitter.homogeneous cimport HomogeneousVolumeEmitter from raysect.optical.material.material cimport NullVolume diff --git a/raysect/optical/material/emitter/unity.pyx b/raysect/optical/material/emitter/unity.pyx index 0666ab7b..a3fc2bea 100644 --- a/raysect/optical/material/emitter/unity.pyx +++ b/raysect/optical/material/emitter/unity.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -29,6 +29,8 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +from raysect.optical cimport World, Primitive, Ray, Spectrum, Point3D, Vector3D, Normal3D, AffineMatrix3D, Intersection + cimport cython diff --git a/raysect/optical/material/lambert.pyx b/raysect/optical/material/lambert.pyx index ba1fe3bb..a3ecd08b 100644 --- a/raysect/optical/material/lambert.pyx +++ b/raysect/optical/material/lambert.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,7 +32,6 @@ from raysect.core.math.sampler cimport HemisphereCosineSampler from raysect.optical cimport Point3D, Vector3D, AffineMatrix3D, Primitive, World, Ray, Spectrum, SpectralFunction, ConstantSF, Intersection from raysect.optical.material cimport ContinuousBSDF -from numpy cimport ndarray cdef HemisphereCosineSampler hemisphere_sampler = HemisphereCosineSampler() diff --git a/raysect/optical/material/material.pxd b/raysect/optical/material/material.pxd index 4bb2617b..f7392016 100644 --- a/raysect/optical/material/material.pxd +++ b/raysect/optical/material/material.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/material.pyx b/raysect/optical/material/material.pyx index 01ab33e7..543694ff 100644 --- a/raysect/optical/material/material.pyx +++ b/raysect/optical/material/material.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/meson.build b/raysect/optical/material/meson.build new file mode 100644 index 00000000..472d4a2a --- /dev/null +++ b/raysect/optical/material/meson.build @@ -0,0 +1,31 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/material' + +# source files +py_files = ['__init__.py'] +pyx_files = ['absorber.pyx', 'conductor.pyx', 'debug.pyx', 'dielectric.pyx', 'lambert.pyx', 'material.pyx'] +pxd_files = ['__init__.pxd', 'absorber.pxd', 'conductor.pxd', 'debug.pxd', 'dielectric.pxd', 'material.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('emitter') +subdir('modifiers') diff --git a/raysect/optical/material/modifiers/__init__.py b/raysect/optical/material/modifiers/__init__.py index 17141bce..73485c44 100644 --- a/raysect/optical/material/modifiers/__init__.py +++ b/raysect/optical/material/modifiers/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/modifiers/add.pyx b/raysect/optical/material/modifiers/add.pyx index 450231db..7bcd5fa7 100644 --- a/raysect/optical/material/modifiers/add.pyx +++ b/raysect/optical/material/modifiers/add.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/modifiers/blend.pyx b/raysect/optical/material/modifiers/blend.pyx index 5e03c10d..c059a07b 100644 --- a/raysect/optical/material/modifiers/blend.pyx +++ b/raysect/optical/material/modifiers/blend.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/material/modifiers/meson.build b/raysect/optical/material/modifiers/meson.build new file mode 100644 index 00000000..cba3666c --- /dev/null +++ b/raysect/optical/material/modifiers/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/material/modifiers' + +# source files +py_files = ['__init__.py'] +pyx_files = ['add.pyx', 'blend.pyx', 'roughen.pyx', 'transform.pyx'] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/optical/material/modifiers/roughen.pyx b/raysect/optical/material/modifiers/roughen.pyx index d705b1f7..b95da76f 100644 --- a/raysect/optical/material/modifiers/roughen.pyx +++ b/raysect/optical/material/modifiers/roughen.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -36,7 +36,8 @@ from raysect.optical.material cimport Material # sets the maximum number of attempts to find a valid perturbed normal # it is highly unlikely (REALLY!) this number will ever be reached, it is just there for my paranoia # in the worst case 50% of the random hemisphere will always generate a valid solution... so P(fail) < 0.5^50! -DEF SAMPLE_ATTEMPTS = 50 +cdef enum: + SAMPLE_ATTEMPTS = 50 cdef HemisphereCosineSampler hemisphere_sampler = HemisphereCosineSampler() diff --git a/raysect/optical/material/modifiers/transform.pyx b/raysect/optical/material/modifiers/transform.pyx index 3ef77f86..eac58c9d 100644 --- a/raysect/optical/material/modifiers/transform.pyx +++ b/raysect/optical/material/modifiers/transform.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/meson.build b/raysect/optical/meson.build new file mode 100644 index 00000000..6d763bbd --- /dev/null +++ b/raysect/optical/meson.build @@ -0,0 +1,33 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical' + +# source files +py_files = ['__init__.py'] +pyx_files = ['colour.pyx', 'loggingray.pyx', 'ray.pyx', 'spectralfunction.pyx', 'spectrum.pyx'] +pxd_files = ['__init__.pxd', 'colour.pxd', 'ray.pxd', 'spectralfunction.pxd', 'spectrum.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('library') +subdir('material') +subdir('observer') +subdir('scenegraph') diff --git a/raysect/optical/observer/__init__.pxd b/raysect/optical/observer/__init__.pxd index 54bae438..8e401ed9 100644 --- a/raysect/optical/observer/__init__.pxd +++ b/raysect/optical/observer/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/__init__.py b/raysect/optical/observer/__init__.py index f41a292f..40153755 100644 --- a/raysect/optical/observer/__init__.py +++ b/raysect/optical/observer/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/base/__init__.pxd b/raysect/optical/observer/base/__init__.pxd index fe7b1d76..e49d93a0 100644 --- a/raysect/optical/observer/base/__init__.pxd +++ b/raysect/optical/observer/base/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/base/__init__.py b/raysect/optical/observer/base/__init__.py index c03e71b3..62c41a2f 100644 --- a/raysect/optical/observer/base/__init__.py +++ b/raysect/optical/observer/base/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/base/meson.build b/raysect/optical/observer/base/meson.build new file mode 100644 index 00000000..d8495643 --- /dev/null +++ b/raysect/optical/observer/base/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/observer/base' + +# source files +py_files = ['__init__.py'] +pyx_files = ['observer.pyx', 'pipeline.pyx', 'processor.pyx', 'sampler.pyx', 'slice.pyx'] +pxd_files = ['__init__.pxd', 'observer.pxd', 'pipeline.pxd', 'processor.pxd', 'sampler.pxd', 'slice.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/optical/observer/base/observer.pxd b/raysect/optical/observer/base/observer.pxd index dddc57fd..39602353 100644 --- a/raysect/optical/observer/base/observer.pxd +++ b/raysect/optical/observer/base/observer.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -55,31 +55,18 @@ cdef class _ObserverBase(Observer): public bint quiet cpdef list _slice_spectrum(self) - cpdef list _generate_templates(self, list slices) - cpdef object _render_pixel(self, tuple task, int slice_id, Ray template) - cpdef object _update_state(self, tuple packed_result, int slice_id) - cpdef list _generate_tasks(self) - cpdef list _obtain_pixel_processors(self, tuple task, int slice_id) - cpdef object _initialise_pipelines(self, double min_wavelength, double max_wavelength, int spectral_bins, list slices, bint quiet) - cpdef object _update_pipelines(self, tuple task, list results, int slice_id) - cpdef object _finalise_pipelines(self) - cpdef object _initialise_statistics(self, list tasks) - cpdef object _update_statistics(self, uint64_t sample_ray_count) - cpdef object _finalise_statistics(self) - cpdef list _obtain_rays(self, tuple task, Ray template) - cpdef double _obtain_sensitivity(self, tuple task) @@ -91,7 +78,6 @@ cdef class Observer0D(_ObserverBase): int _samples_per_task cpdef list _generate_rays(self, Ray template, int ray_count) - cpdef double _pixel_sensitivity(self) @@ -104,7 +90,6 @@ cdef class Observer1D(_ObserverBase): int _pixel_samples cpdef list _generate_rays(self, int pixel, Ray template, int ray_count) - cpdef double _pixel_sensitivity(self, int pixel) @@ -117,7 +102,6 @@ cdef class Observer2D(_ObserverBase): int _pixel_samples cpdef list _generate_rays(self, int x, int y, Ray template, int ray_count) - cpdef double _pixel_sensitivity(self, int x, int y) diff --git a/raysect/optical/observer/base/observer.pyx b/raysect/optical/observer/base/observer.pyx index 5afdd7fb..66c7705b 100644 --- a/raysect/optical/observer/base/observer.pyx +++ b/raysect/optical/observer/base/observer.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/base/pipeline.pxd b/raysect/optical/observer/base/pipeline.pxd index a5f96b2b..0b6be0c2 100644 --- a/raysect/optical/observer/base/pipeline.pxd +++ b/raysect/optical/observer/base/pipeline.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -35,32 +35,23 @@ from raysect.optical.observer.base.processor cimport PixelProcessor cdef class Pipeline0D: cpdef object initialise(self, double min_wavelength, double max_wavelength, int spectral_bins, list spectral_slices, bint quiet) - cpdef PixelProcessor pixel_processor(self, int slice_id) - cpdef object update(self, int slice_id, tuple packed_result, int samples) - cpdef object finalise(self) cdef class Pipeline1D: cpdef object initialise(self, int pixels, int pixel_samples, double min_wavelength, double max_wavelength, int spectral_bins, list spectral_slices, bint quiet) - cpdef PixelProcessor pixel_processor(self, int pixel, int slice_id) - cpdef object update(self, int pixel, int slice_id, tuple packed_result) - cpdef object finalise(self) cdef class Pipeline2D: cpdef object initialise(self, tuple pixels, int pixel_samples, double min_wavelength, double max_wavelength, int spectral_bins, list spectral_slices, bint quiet) - cpdef PixelProcessor pixel_processor(self, int x, int y, int slice_id) - cpdef object update(self, int x, int y, int slice_id, tuple packed_result) - cpdef object finalise(self) diff --git a/raysect/optical/observer/base/pipeline.pyx b/raysect/optical/observer/base/pipeline.pyx index 1ae47d67..802b3a8e 100644 --- a/raysect/optical/observer/base/pipeline.pyx +++ b/raysect/optical/observer/base/pipeline.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/base/processor.pxd b/raysect/optical/observer/base/processor.pxd index d3f80fe4..10dbc820 100644 --- a/raysect/optical/observer/base/processor.pxd +++ b/raysect/optical/observer/base/processor.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,9 +31,9 @@ from raysect.optical cimport Spectrum + cdef class PixelProcessor: cpdef object add_sample(self, Spectrum spectrum, double sensitivity) - cpdef tuple pack_results(self) diff --git a/raysect/optical/observer/base/processor.pyx b/raysect/optical/observer/base/processor.pyx index b283b1f5..ecf98dd7 100644 --- a/raysect/optical/observer/base/processor.pyx +++ b/raysect/optical/observer/base/processor.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,6 +31,7 @@ cimport cython + @cython.freelist(64) cdef class PixelProcessor: """ diff --git a/raysect/optical/observer/base/sampler.pxd b/raysect/optical/observer/base/sampler.pxd index e78a2299..c80a9d09 100644 --- a/raysect/optical/observer/base/sampler.pxd +++ b/raysect/optical/observer/base/sampler.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/base/sampler.pyx b/raysect/optical/observer/base/sampler.pyx index 3ff41d8b..7c595f40 100644 --- a/raysect/optical/observer/base/sampler.pyx +++ b/raysect/optical/observer/base/sampler.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/base/slice.pxd b/raysect/optical/observer/base/slice.pxd index 0a411be8..68b8f5fd 100644 --- a/raysect/optical/observer/base/slice.pxd +++ b/raysect/optical/observer/base/slice.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/base/slice.pyx b/raysect/optical/observer/base/slice.pyx index 6cacc8a0..20848f80 100644 --- a/raysect/optical/observer/base/slice.pyx +++ b/raysect/optical/observer/base/slice.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/imaging/__init__.pxd b/raysect/optical/observer/imaging/__init__.pxd index 88b0bcc2..946850b4 100644 --- a/raysect/optical/observer/imaging/__init__.pxd +++ b/raysect/optical/observer/imaging/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ # POSSIBILITY OF SUCH DAMAGE. from raysect.optical.observer.imaging.ccd cimport CCDArray -from raysect.optical.observer.imaging.targetted_ccd cimport TargettedCCDArray +from raysect.optical.observer.imaging.targeted_ccd cimport TargetedCCDArray from raysect.optical.observer.imaging.orthographic cimport OrthographicCamera from raysect.optical.observer.imaging.pinhole cimport PinholeCamera from raysect.optical.observer.imaging.vector cimport VectorCamera diff --git a/raysect/optical/observer/imaging/__init__.py b/raysect/optical/observer/imaging/__init__.py index 4dc11805..0028eedc 100644 --- a/raysect/optical/observer/imaging/__init__.py +++ b/raysect/optical/observer/imaging/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ # POSSIBILITY OF SUCH DAMAGE. from .ccd import CCDArray -from .targetted_ccd import TargettedCCDArray +from .targeted_ccd import TargetedCCDArray from .orthographic import OrthographicCamera from .pinhole import PinholeCamera from .vector import VectorCamera diff --git a/raysect/optical/observer/imaging/ccd.pxd b/raysect/optical/observer/imaging/ccd.pxd index f9be4281..c49fbcaa 100644 --- a/raysect/optical/observer/imaging/ccd.pxd +++ b/raysect/optical/observer/imaging/ccd.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/imaging/ccd.pyx b/raysect/optical/observer/imaging/ccd.pyx index 9af15b09..7483f0a3 100644 --- a/raysect/optical/observer/imaging/ccd.pyx +++ b/raysect/optical/observer/imaging/ccd.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/imaging/meson.build b/raysect/optical/observer/imaging/meson.build new file mode 100644 index 00000000..85a7aaa6 --- /dev/null +++ b/raysect/optical/observer/imaging/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/observer/imaging' + +# source files +py_files = ['__init__.py'] +pyx_files = ['ccd.pyx', 'opencv.pyx', 'orthographic.pyx', 'pinhole.pyx', 'targeted_ccd.pyx', 'vector.pyx'] +pxd_files = ['__init__.pxd', 'ccd.pxd', 'opencv.pxd', 'orthographic.pxd', 'pinhole.pxd', 'targeted_ccd.pxd', 'vector.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/optical/observer/imaging/opencv.pxd b/raysect/optical/observer/imaging/opencv.pxd index 5070dd63..bbb0b6d5 100644 --- a/raysect/optical/observer/imaging/opencv.pxd +++ b/raysect/optical/observer/imaging/opencv.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/imaging/opencv.pyx b/raysect/optical/observer/imaging/opencv.pyx index 1c8f3430..b3257dd9 100644 --- a/raysect/optical/observer/imaging/opencv.pyx +++ b/raysect/optical/observer/imaging/opencv.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/imaging/orthographic.pxd b/raysect/optical/observer/imaging/orthographic.pxd index c9ca2b92..0b1acb99 100644 --- a/raysect/optical/observer/imaging/orthographic.pxd +++ b/raysect/optical/observer/imaging/orthographic.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/imaging/orthographic.pyx b/raysect/optical/observer/imaging/orthographic.pyx index 371b9b06..5d0946d2 100644 --- a/raysect/optical/observer/imaging/orthographic.pyx +++ b/raysect/optical/observer/imaging/orthographic.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/imaging/pinhole.pxd b/raysect/optical/observer/imaging/pinhole.pxd index 121a57d6..bb3bbb3b 100644 --- a/raysect/optical/observer/imaging/pinhole.pxd +++ b/raysect/optical/observer/imaging/pinhole.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/imaging/pinhole.pyx b/raysect/optical/observer/imaging/pinhole.pyx index ec05847d..b7876db1 100644 --- a/raysect/optical/observer/imaging/pinhole.pyx +++ b/raysect/optical/observer/imaging/pinhole.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/imaging/targetted_ccd.pxd b/raysect/optical/observer/imaging/targeted_ccd.pxd similarity index 88% rename from raysect/optical/observer/imaging/targetted_ccd.pxd rename to raysect/optical/observer/imaging/targeted_ccd.pxd index a3de79b8..4e7fb777 100644 --- a/raysect/optical/observer/imaging/targetted_ccd.pxd +++ b/raysect/optical/observer/imaging/targeted_ccd.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -29,17 +29,17 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -from raysect.core.math.sampler cimport RectangleSampler3D, HemisphereCosineSampler, TargettedHemisphereSampler +from raysect.core.math.sampler cimport RectangleSampler3D, HemisphereCosineSampler, TargetedHemisphereSampler from raysect.optical.observer.base cimport Observer2D -cdef class TargettedCCDArray(Observer2D): +cdef class TargetedCCDArray(Observer2D): cdef: - double _width, _pixel_area, _image_delta, _image_start_x, _image_start_y, _targetted_path_prob + double _width, _pixel_area, _image_delta, _image_start_x, _image_start_y, _targeted_path_prob tuple _targets RectangleSampler3D _point_sampler HemisphereCosineSampler _cosine_sampler - TargettedHemisphereSampler _targetted_sampler + TargetedHemisphereSampler _targeted_sampler cdef object _update_image_geometry(self) diff --git a/raysect/optical/observer/imaging/targetted_ccd.pyx b/raysect/optical/observer/imaging/targeted_ccd.pyx similarity index 86% rename from raysect/optical/observer/imaging/targetted_ccd.pyx rename to raysect/optical/observer/imaging/targeted_ccd.pyx index cb355626..5daa7468 100644 --- a/raysect/optical/observer/imaging/targetted_ccd.pyx +++ b/raysect/optical/observer/imaging/targeted_ccd.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -33,34 +33,34 @@ from raysect.core.math.random cimport probability from raysect.optical.observer.sampler2d import FullFrameSampler2D from raysect.optical.observer.pipeline import RGBPipeline2D -from raysect.core.math.sampler cimport RectangleSampler3D, HemisphereCosineSampler, TargettedHemisphereSampler +from raysect.core.math.sampler cimport RectangleSampler3D, HemisphereCosineSampler, TargetedHemisphereSampler from raysect.optical cimport Primitive, BoundingSphere3D, Ray, AffineMatrix3D, Point3D, Vector3D, translate from libc.math cimport M_PI from raysect.optical.observer.base cimport Observer2D cimport cython -DEF R_2_PI = 0.15915494309189535 # 1 / (2 * pi) +cdef const double R_2_PI = 0.15915494309189535 # 1 / (2 * pi) -cdef class TargettedCCDArray(Observer2D): +cdef class TargetedCCDArray(Observer2D): """ An ideal CCD-like imaging sensor that preferentially targets a given list of primitives. - The targetted CCD is a regular array of square pixels. Each pixel samples red, green + The targeted CCD is a regular array of square pixels. Each pixel samples red, green and blue channels (behaves like a Foveon imaging sensor). The CCD sensor width is specified with the width parameter. The CCD height is calculated from the width and the number of vertical and horizontal pixels. The default width and sensor ratio approximates a 35mm camera sensor. - The targetted CCD takes a list of target primitives. Each pixel will target the + The targeted CCD takes a list of target primitives. Each pixel will target the bounding spheres that encompass each target primitive. Therefore, for best performance, the target primitives should be split up such that their surfaces are closely wrapped by the bounding sphere. The sampling algorithm fires a proportion of rays at the targets, and a portion sampled from the full hemisphere. The proportion that is fired towards the targets is controlled - with the targetted_path_prob attribute. By default this attribute is set to 0.9, i.e. + with the targeted_path_prob attribute. By default this attribute is set to 0.9, i.e. 90% of the rays are fired towards the targets. .. Warning.. @@ -68,7 +68,7 @@ cdef class TargettedCCDArray(Observer2D): targets. The user must ensure there are no sources of radiance outside of the targeted directions, otherwise they will not be sampled and the result will be biased. - :param list targets: The list of primitives for targetted sampling. + :param list targets: The list of primitives for targeted sampling. :param tuple pixels: A tuple of pixel dimensions for the camera (default=(720, 480)). :param float width: The CCD sensor x-width in metres (default=35mm). :param list pipelines: The list of pipelines that will process the spectrum measured @@ -76,7 +76,7 @@ cdef class TargettedCCDArray(Observer2D): :param kwargs: **kwargs and properties from Observer2D and _ObserverBase. """ - def __init__(self, targets, pixels=(720, 480), width=0.035, targetted_path_prob=None, parent=None, transform=None, name=None, pipelines=None): + def __init__(self, targets, pixels=(720, 480), width=0.035, targeted_path_prob=None, parent=None, transform=None, name=None, pipelines=None): # initial values to prevent undefined behaviour when setting via self.width self._width = 0.035 @@ -88,12 +88,12 @@ cdef class TargettedCCDArray(Observer2D): parent=parent, transform=transform, name=name) self._cosine_sampler = HemisphereCosineSampler() - self._targetted_sampler = None + self._targeted_sampler = None # setting width triggers calculation of image geometry calculations self.width = width self.targets = targets - self.targetted_path_prob = targetted_path_prob or 0.9 + self.targeted_path_prob = targeted_path_prob or 0.9 @property def pixels(self): @@ -158,7 +158,7 @@ cdef class TargettedCCDArray(Observer2D): self._targets = value @property - def targetted_path_prob(self): + def targeted_path_prob(self): """ The probability that an individual sample will be fired at a target instead of a sample from the whole hemisphere. @@ -169,14 +169,14 @@ cdef class TargettedCCDArray(Observer2D): :rtype: float """ - return self._targetted_path_prob + return self._targeted_path_prob - @targetted_path_prob.setter - def targetted_path_prob(self, double value): + @targeted_path_prob.setter + def targeted_path_prob(self, double value): if value < 0 or value > 1: raise ValueError("Targeted path probability must lie in the range [0, 1].") - self._targetted_path_prob = value + self._targeted_path_prob = value cdef object _update_image_geometry(self): @@ -212,8 +212,8 @@ cdef class TargettedCCDArray(Observer2D): sphere = target.bounding_sphere() spheres.append((sphere.centre.transform(self.to_local()), sphere.radius, 1.0)) - # instance targetted pixel sampler - self._targetted_sampler = TargettedHemisphereSampler(spheres) + # instance targeted pixel sampler + self._targeted_sampler = TargetedHemisphereSampler(spheres) # generate pixel transform pixel_x = self._image_start_x - self._image_delta * (ix + 0.5) @@ -230,17 +230,17 @@ cdef class TargettedCCDArray(Observer2D): # transform to local space from pixel space origin = origin.transform(pixel_to_local) - if probability(self._targetted_path_prob): - # obtain targetted vector sample - direction = self._targetted_sampler.sample(origin) + if probability(self._targeted_path_prob): + # obtain targeted vector sample + direction = self._targeted_sampler.sample(origin) else: # obtain cosine weighted hemisphere sample direction = self._cosine_sampler.sample() # calculate combined pdf and ray weight - pdf = self._targetted_path_prob * self._targetted_sampler.pdf(origin, direction) + \ - (1-self._targetted_path_prob) * self._cosine_sampler.pdf(direction) + pdf = self._targeted_path_prob * self._targeted_sampler.pdf(origin, direction) + \ + (1-self._targeted_path_prob) * self._cosine_sampler.pdf(direction) if pdf <= 0: raise ValueError('Ray direction probability is zero. The target object extends beyond the pixel horizon.') diff --git a/raysect/optical/observer/imaging/vector.pxd b/raysect/optical/observer/imaging/vector.pxd index d9d5f4bf..f5c5830d 100644 --- a/raysect/optical/observer/imaging/vector.pxd +++ b/raysect/optical/observer/imaging/vector.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/imaging/vector.pyx b/raysect/optical/observer/imaging/vector.pyx index 25aa6f86..dd73fd5f 100644 --- a/raysect/optical/observer/imaging/vector.pyx +++ b/raysect/optical/observer/imaging/vector.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/meson.build b/raysect/optical/observer/meson.build new file mode 100644 index 00000000..a4ad306a --- /dev/null +++ b/raysect/optical/observer/meson.build @@ -0,0 +1,33 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/observer' + +# source files +py_files = ['__init__.py'] +pyx_files = ['sampler1d.pyx', 'sampler2d.pyx'] +pxd_files = ['__init__.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('base') +subdir('imaging') +subdir('nonimaging') +subdir('pipeline') diff --git a/raysect/optical/observer/nonimaging/__init__.pxd b/raysect/optical/observer/nonimaging/__init__.pxd index 880166a6..f550d902 100644 --- a/raysect/optical/observer/nonimaging/__init__.pxd +++ b/raysect/optical/observer/nonimaging/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,7 +32,7 @@ from raysect.optical.observer.nonimaging.sightline import SightLine from raysect.optical.observer.nonimaging.fibreoptic import FibreOptic from raysect.optical.observer.nonimaging.pixel import Pixel -from raysect.optical.observer.nonimaging.targetted_pixel import TargettedPixel +from raysect.optical.observer.nonimaging.targeted_pixel import TargetedPixel from raysect.optical.observer.nonimaging.mesh_pixel import MeshPixel from raysect.optical.observer.nonimaging.mesh_camera import MeshCamera diff --git a/raysect/optical/observer/nonimaging/__init__.py b/raysect/optical/observer/nonimaging/__init__.py index 0a800447..2b04ab5f 100644 --- a/raysect/optical/observer/nonimaging/__init__.py +++ b/raysect/optical/observer/nonimaging/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,7 +32,7 @@ from .sightline import SightLine from .fibreoptic import FibreOptic from .pixel import Pixel -from .targetted_pixel import TargettedPixel +from .targeted_pixel import TargetedPixel from .mesh_pixel import MeshPixel from .mesh_camera import MeshCamera diff --git a/raysect/optical/observer/nonimaging/fibreoptic.pxd b/raysect/optical/observer/nonimaging/fibreoptic.pxd index ced7d611..8033ca4b 100644 --- a/raysect/optical/observer/nonimaging/fibreoptic.pxd +++ b/raysect/optical/observer/nonimaging/fibreoptic.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/nonimaging/fibreoptic.pyx b/raysect/optical/observer/nonimaging/fibreoptic.pyx index c3fde275..b9810367 100644 --- a/raysect/optical/observer/nonimaging/fibreoptic.pyx +++ b/raysect/optical/observer/nonimaging/fibreoptic.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -40,7 +40,7 @@ cimport cython # 1 / (2 * PI) -DEF RECIP_2_PI = 0.15915494309189535 +cdef const double RECIP_2_PI = 0.15915494309189535 # TODO - provide a function for angular fall off for collection, instead of acceptance cone. diff --git a/raysect/optical/observer/nonimaging/mesh_camera.pxd b/raysect/optical/observer/nonimaging/mesh_camera.pxd index 1ebda160..2820ed19 100644 --- a/raysect/optical/observer/nonimaging/mesh_camera.pxd +++ b/raysect/optical/observer/nonimaging/mesh_camera.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/nonimaging/mesh_camera.pyx b/raysect/optical/observer/nonimaging/mesh_camera.pyx index 79b5aabf..60b1af97 100644 --- a/raysect/optical/observer/nonimaging/mesh_camera.pyx +++ b/raysect/optical/observer/nonimaging/mesh_camera.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -43,14 +43,19 @@ from raysect.optical.observer.sampler1d import FullFrameSampler1D from raysect.primitive.mesh.mesh cimport Mesh cimport cython -# convenience defines -DEF X = 0 -DEF Y = 1 -DEF Z = 2 -DEF V1 = 0 -DEF V2 = 1 -DEF V3 = 2 +# constants +cdef enum: + + # axis + X = 0 + Y = 1 + Z = 2 + + # vertex + V1 = 0 + V2 = 1 + V3 = 2 cdef class MeshCamera(Observer1D): diff --git a/raysect/optical/observer/nonimaging/mesh_pixel.pxd b/raysect/optical/observer/nonimaging/mesh_pixel.pxd index ec0a3055..3ff29c43 100644 --- a/raysect/optical/observer/nonimaging/mesh_pixel.pxd +++ b/raysect/optical/observer/nonimaging/mesh_pixel.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/nonimaging/mesh_pixel.pyx b/raysect/optical/observer/nonimaging/mesh_pixel.pyx index 61a7479a..9ed81706 100644 --- a/raysect/optical/observer/nonimaging/mesh_pixel.pyx +++ b/raysect/optical/observer/nonimaging/mesh_pixel.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -43,14 +43,19 @@ from raysect.optical.observer.pipeline.spectral import SpectralPowerPipeline0D from raysect.primitive.mesh.mesh cimport Mesh cimport cython -# convenience defines -DEF X = 0 -DEF Y = 1 -DEF Z = 2 -DEF V1 = 0 -DEF V2 = 1 -DEF V3 = 2 +# constants +cdef enum: + + # axis + X = 0 + Y = 1 + Z = 2 + + # vertex + V1 = 0 + V2 = 1 + V3 = 2 cdef class MeshPixel(Observer0D): @@ -167,8 +172,8 @@ cdef class MeshPixel(Observer0D): self._collection_area = 0.0 self._cdf = np.zeros(self._triangles_mv.shape[0]) self._cdf_mv = self._cdf - - # calculate cumulative and total area simultaneously + + # calculate cumulative and total area simultaneously for i in range(self._triangles_mv.shape[0]): # obtain vertex indices @@ -184,7 +189,7 @@ cdef class MeshPixel(Observer0D): ) self._collection_area += triangle_area self._cdf_mv[i] = self._collection_area - + # normalise cumulative area to make cdf self._cdf /= self._collection_area diff --git a/raysect/optical/observer/nonimaging/meson.build b/raysect/optical/observer/nonimaging/meson.build new file mode 100644 index 00000000..6ba3a60d --- /dev/null +++ b/raysect/optical/observer/nonimaging/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/observer/nonimaging' + +# source files +py_files = ['__init__.py'] +pyx_files = ['fibreoptic.pyx', 'mesh_camera.pyx', 'mesh_pixel.pyx', 'pixel.pyx', 'sightline.pyx', 'targeted_pixel.pyx'] +pxd_files = ['__init__.pxd', 'fibreoptic.pxd', 'mesh_camera.pxd', 'mesh_pixel.pxd', 'pixel.pxd', 'sightline.pxd', 'targeted_pixel.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/optical/observer/nonimaging/pixel.pxd b/raysect/optical/observer/nonimaging/pixel.pxd index 0da277db..5dba6ef8 100644 --- a/raysect/optical/observer/nonimaging/pixel.pxd +++ b/raysect/optical/observer/nonimaging/pixel.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/nonimaging/pixel.pyx b/raysect/optical/observer/nonimaging/pixel.pyx index ad9e760c..261749f2 100644 --- a/raysect/optical/observer/nonimaging/pixel.pyx +++ b/raysect/optical/observer/nonimaging/pixel.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/nonimaging/sightline.pxd b/raysect/optical/observer/nonimaging/sightline.pxd index 0ae360d8..a99161ac 100644 --- a/raysect/optical/observer/nonimaging/sightline.pxd +++ b/raysect/optical/observer/nonimaging/sightline.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/nonimaging/sightline.pyx b/raysect/optical/observer/nonimaging/sightline.pyx index 9a354106..f830916e 100644 --- a/raysect/optical/observer/nonimaging/sightline.pyx +++ b/raysect/optical/observer/nonimaging/sightline.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/nonimaging/targetted_pixel.pxd b/raysect/optical/observer/nonimaging/targeted_pixel.pxd similarity index 89% rename from raysect/optical/observer/nonimaging/targetted_pixel.pxd rename to raysect/optical/observer/nonimaging/targeted_pixel.pxd index 0f7c8402..378a6a12 100644 --- a/raysect/optical/observer/nonimaging/targetted_pixel.pxd +++ b/raysect/optical/observer/nonimaging/targeted_pixel.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -29,15 +29,15 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -from raysect.core.math.sampler cimport RectangleSampler3D, HemisphereCosineSampler, TargettedHemisphereSampler +from raysect.core.math.sampler cimport RectangleSampler3D, HemisphereCosineSampler, TargetedHemisphereSampler from raysect.optical.observer.base cimport Observer0D -cdef class TargettedPixel(Observer0D): +cdef class TargetedPixel(Observer0D): cdef: - double _x_width, _y_width, _solid_angle, _collection_area, _targetted_path_prob + double _x_width, _y_width, _solid_angle, _collection_area, _targeted_path_prob tuple _targets RectangleSampler3D _point_sampler HemisphereCosineSampler _cosine_sampler - TargettedHemisphereSampler _targetted_sampler + TargetedHemisphereSampler _targeted_sampler diff --git a/raysect/optical/observer/nonimaging/targetted_pixel.pyx b/raysect/optical/observer/nonimaging/targeted_pixel.pyx similarity index 85% rename from raysect/optical/observer/nonimaging/targetted_pixel.pyx rename to raysect/optical/observer/nonimaging/targeted_pixel.pyx index b83b07a0..4a8d2c07 100644 --- a/raysect/optical/observer/nonimaging/targetted_pixel.pyx +++ b/raysect/optical/observer/nonimaging/targeted_pixel.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,28 +32,28 @@ from libc.math cimport M_PI as PI from raysect.core.math.random cimport probability -from raysect.core.math.sampler cimport RectangleSampler3D, HemisphereCosineSampler, TargettedHemisphereSampler +from raysect.core.math.sampler cimport RectangleSampler3D, HemisphereCosineSampler, TargetedHemisphereSampler from raysect.optical cimport Ray, Primitive, Point3D, Vector3D, BoundingSphere3D from raysect.optical.observer.base cimport Observer0D from raysect.optical.observer.pipeline.spectral import SpectralPowerPipeline0D cimport cython -DEF R_2_PI = 0.15915494309189535 # 1 / (2 * pi) +cdef const double R_2_PI = 0.15915494309189535 # 1 / (2 * pi) -cdef class TargettedPixel(Observer0D): +cdef class TargetedPixel(Observer0D): """ A pixel observer that preferentially targets rays towards a given list of primitives. - The targetted pixel takes a list of target primitives. The observer targets the + The targeted pixel takes a list of target primitives. The observer targets the bounding sphere that encompasses a target primitive. Therefore, for best performance, the target primitives should be split up such that their surfaces are closely wrapped by the bounding sphere. The sampling algorithm fires a proportion of rays at the targets, and a portion sampled from the full hemisphere. The proportion that is fired towards the targets is controlled - with the targetted_path_prob attribute. By default this attribute is set to 0.9, i.e. + with the targeted_path_prob attribute. By default this attribute is set to 0.9, i.e. 90% of the rays are fired towards the targets. .. Warning.. @@ -62,7 +62,7 @@ cdef class TargettedPixel(Observer0D): targeted directions, otherwise they will not be sampled and the result will be biased. :param list targets: The list of primitives for targeted sampling. - :param float targetted_path_prob: The probability of sampling a targeted primitive VS sampling over the whole hemisphere. + :param float targeted_path_prob: The probability of sampling a targeted primitive VS sampling over the whole hemisphere. :param list pipelines: The list of pipelines that will process the spectrum measured by this pixel (default=SpectralPipeline0D()). :param float x_width: The rectangular collection area's width along the @@ -73,21 +73,21 @@ cdef class TargettedPixel(Observer0D): .. code-block:: pycon - >>> from raysect.optical.observer import TargettedPixel, PowerPipeline0D + >>> from raysect.optical.observer import TargetedPixel, PowerPipeline0D >>> >>> # set-up scenegraph >>> world = World() >>> emitter = Sphere(radius=sphere_radius, parent=world) >>> emitter.material = UnityVolumeEmitter() >>> - >>> # setup targetted pixel observer - >>> targetted_pipeline = PowerPipeline0D(name="Targeted Pixel Observer") - >>> targetted_pixel = TargettedPixel(parent=world, targets=[emitter], - >>> pixel_samples=250, pipelines=[targetted_pipeline]) - >>> targetted_pixel.observe() + >>> # setup targeted pixel observer + >>> targeted_pipeline = PowerPipeline0D(name="Targeted Pixel Observer") + >>> targeted_pixel = TargetedPixel(parent=world, targets=[emitter], + >>> pixel_samples=250, pipelines=[targeted_pipeline]) + >>> targeted_pixel.observe() """ - def __init__(self, targets, targetted_path_prob=None, + def __init__(self, targets, targeted_path_prob=None, pipelines=None, x_width=None, y_width=None, parent=None, transform=None, name=None, render_engine=None, pixel_samples=None, samples_per_task=None, spectral_rays=None, spectral_bins=None, min_wavelength=None, max_wavelength=None, ray_extinction_prob=None, ray_extinction_min_depth=None, @@ -105,14 +105,14 @@ cdef class TargettedPixel(Observer0D): self._x_width = 0.01 self._y_width = 0.01 self._cosine_sampler = HemisphereCosineSampler() - self._targetted_sampler = None + self._targeted_sampler = None self._solid_angle = 2 * PI self.x_width = x_width or 0.01 self.y_width = y_width or 0.01 self.targets = targets - self.targetted_path_prob = targetted_path_prob or 0.9 + self.targeted_path_prob = targeted_path_prob or 0.9 @property def x_width(self): @@ -205,7 +205,7 @@ cdef class TargettedPixel(Observer0D): self._targets = value @property - def targetted_path_prob(self): + def targeted_path_prob(self): """ The probability that an individual sample will be fired at a target instead of a sample from the whole hemisphere. @@ -216,14 +216,14 @@ cdef class TargettedPixel(Observer0D): :rtype: float """ - return self._targetted_path_prob + return self._targeted_path_prob - @targetted_path_prob.setter - def targetted_path_prob(self, double value): + @targeted_path_prob.setter + def targeted_path_prob(self, double value): if value < 0 or value > 1: raise ValueError("Targeted path probability must lie in the range [0, 1].") - self._targetted_path_prob = value + self._targeted_path_prob = value @cython.boundscheck(False) @cython.wraparound(False) @@ -249,8 +249,8 @@ cdef class TargettedPixel(Observer0D): sphere = target.bounding_sphere() spheres.append((sphere.centre.transform(self.to_local()), sphere.radius, 1.0)) - # instance targetted pixel sampler - self._targetted_sampler = TargettedHemisphereSampler(spheres) + # instance targeted pixel sampler + self._targeted_sampler = TargetedHemisphereSampler(spheres) # sample pixel origins origins = self._point_sampler.samples(ray_count) @@ -258,17 +258,17 @@ cdef class TargettedPixel(Observer0D): rays = [] for origin in origins: - if probability(self._targetted_path_prob): - # obtain targetted vector sample - direction = self._targetted_sampler.sample(origin) + if probability(self._targeted_path_prob): + # obtain targeted vector sample + direction = self._targeted_sampler.sample(origin) else: # obtain cosine weighted hemisphere sample direction = self._cosine_sampler.sample() # calculate combined pdf and ray weight - pdf = self._targetted_path_prob * self._targetted_sampler.pdf(origin, direction) + \ - (1-self._targetted_path_prob) * self._cosine_sampler.pdf(direction) + pdf = self._targeted_path_prob * self._targeted_sampler.pdf(origin, direction) + \ + (1-self._targeted_path_prob) * self._cosine_sampler.pdf(direction) if pdf <= 0: raise ValueError('Ray direction probability is zero. The target object extends beyond the pixel horizon.') diff --git a/raysect/optical/observer/pipeline/__init__.pxd b/raysect/optical/observer/pipeline/__init__.pxd index 8ad13376..ebbd41a4 100644 --- a/raysect/optical/observer/pipeline/__init__.pxd +++ b/raysect/optical/observer/pipeline/__init__.pxd @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/pipeline/__init__.py b/raysect/optical/observer/pipeline/__init__.py index 90cc3043..a9ec73af 100644 --- a/raysect/optical/observer/pipeline/__init__.py +++ b/raysect/optical/observer/pipeline/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/pipeline/bayer.pxd b/raysect/optical/observer/pipeline/bayer.pxd index 6dde0eb4..41d50d31 100644 --- a/raysect/optical/observer/pipeline/bayer.pxd +++ b/raysect/optical/observer/pipeline/bayer.pxd @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,6 +32,7 @@ from raysect.optical.spectralfunction cimport SpectralFunction from raysect.optical.observer.base cimport PixelProcessor, Pipeline2D from raysect.core.math cimport StatsArray2D + cdef class BayerPipeline2D(Pipeline2D): cdef: @@ -56,17 +57,10 @@ cdef class BayerPipeline2D(Pipeline2D): bint _quiet cpdef object _start_display(self) - cpdef object _update_display(self, int x, int y) - cpdef object _refresh_display(self) - cpdef object _render_display(self, StatsArray2D frame, str status=*) - cpdef np.ndarray _generate_display_image(self, StatsArray2D frame) - cpdef double _calculate_white_point(self, np.ndarray image) - cpdef object display(self) - cpdef object save(self, str filename) diff --git a/raysect/optical/observer/pipeline/bayer.pyx b/raysect/optical/observer/pipeline/bayer.pyx index 28a2f100..152fec0d 100644 --- a/raysect/optical/observer/pipeline/bayer.pyx +++ b/raysect/optical/observer/pipeline/bayer.pyx @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -554,8 +554,7 @@ cdef class BayerPipeline2D(Pipeline2D): for i in range(pixels): if lmv[i] > 0: break - - if i == pixels: + else: return self._display_black_point # identify luminance at threshold diff --git a/raysect/optical/observer/pipeline/meson.build b/raysect/optical/observer/pipeline/meson.build new file mode 100644 index 00000000..c5d6f780 --- /dev/null +++ b/raysect/optical/observer/pipeline/meson.build @@ -0,0 +1,31 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/observer/pipeline' + +# source files +py_files = ['__init__.py', 'colormaps.py'] +pyx_files = ['bayer.pyx', 'rgb.pyx'] +pxd_files = ['__init__.pxd', 'bayer.pxd', 'rgb.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('mono') +subdir('spectral') diff --git a/raysect/optical/observer/pipeline/mono/__init__.pxd b/raysect/optical/observer/pipeline/mono/__init__.pxd index 64ec22d0..c3ac54e7 100644 --- a/raysect/optical/observer/pipeline/mono/__init__.pxd +++ b/raysect/optical/observer/pipeline/mono/__init__.pxd @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/pipeline/mono/__init__.py b/raysect/optical/observer/pipeline/mono/__init__.py index 4c2be074..b424cddf 100644 --- a/raysect/optical/observer/pipeline/mono/__init__.py +++ b/raysect/optical/observer/pipeline/mono/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/pipeline/mono/meson.build b/raysect/optical/observer/pipeline/mono/meson.build new file mode 100644 index 00000000..93907700 --- /dev/null +++ b/raysect/optical/observer/pipeline/mono/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/observer/pipeline/mono' + +# source files +py_files = ['__init__.py'] +pyx_files = ['power.pyx', 'radiance.pyx'] +pxd_files = ['__init__.pxd', 'power.pxd', 'radiance.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/optical/observer/pipeline/mono/power.pxd b/raysect/optical/observer/pipeline/mono/power.pxd index 04f2b6ad..347fee1a 100644 --- a/raysect/optical/observer/pipeline/mono/power.pxd +++ b/raysect/optical/observer/pipeline/mono/power.pxd @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -83,19 +83,12 @@ cdef class PowerPipeline2D(Pipeline2D): bint _quiet cpdef object _start_display(self) - cpdef object _update_display(self, int x, int y) - cpdef object _refresh_display(self) - cpdef object _render_display(self, StatsArray2D frame, str status=*) - cpdef np.ndarray _generate_display_image(self, StatsArray2D frame) - cpdef double _calculate_white_point(self, np.ndarray image) - cpdef object display(self) - cpdef object save(self, str filename) diff --git a/raysect/optical/observer/pipeline/mono/power.pyx b/raysect/optical/observer/pipeline/mono/power.pyx index a95d2d1e..f4088daa 100644 --- a/raysect/optical/observer/pipeline/mono/power.pyx +++ b/raysect/optical/observer/pipeline/mono/power.pyx @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -716,8 +716,7 @@ cdef class PowerPipeline2D(Pipeline2D): for i in range(pixels): if lmv[i] > 0: break - - if i == pixels: + else: return self._display_black_point # identify luminance at threshold diff --git a/raysect/optical/observer/pipeline/mono/radiance.pxd b/raysect/optical/observer/pipeline/mono/radiance.pxd index f83aa868..c065334c 100644 --- a/raysect/optical/observer/pipeline/mono/radiance.pxd +++ b/raysect/optical/observer/pipeline/mono/radiance.pxd @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/pipeline/mono/radiance.pyx b/raysect/optical/observer/pipeline/mono/radiance.pyx index a48795c2..3d64209f 100644 --- a/raysect/optical/observer/pipeline/mono/radiance.pyx +++ b/raysect/optical/observer/pipeline/mono/radiance.pyx @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/pipeline/rgb.pxd b/raysect/optical/observer/pipeline/rgb.pxd index bc9ecd2d..35326988 100644 --- a/raysect/optical/observer/pipeline/rgb.pxd +++ b/raysect/optical/observer/pipeline/rgb.pxd @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -54,21 +54,13 @@ cdef class RGBPipeline2D(Pipeline2D): bint _quiet cpdef object _start_display(self) - cpdef object _update_display(self, int x, int y) - cpdef object _refresh_display(self) - cpdef object _render_display(self, StatsArray3D frame, str status=*) - cpdef np.ndarray _generate_display_image(self, StatsArray3D frame) - cpdef double _calculate_sensitivity(self, np.ndarray image) - cpdef np.ndarray _generate_srgb_image(self, double[:,:,::1] xyz_image_mv) - cpdef object display(self) - cpdef object save(self, str filename) diff --git a/raysect/optical/observer/pipeline/rgb.pyx b/raysect/optical/observer/pipeline/rgb.pyx index 1d4afa44..4d6bc65e 100644 --- a/raysect/optical/observer/pipeline/rgb.pyx +++ b/raysect/optical/observer/pipeline/rgb.pyx @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -455,13 +455,14 @@ cdef class RGBPipeline2D(Pipeline2D): # sort by luminance luminance.sort() + # + i = 0 + # if all pixels black, return default sensitivity for i in range(pixels): if lmv[i] > 0: break - - # return default sensitivity - if i == pixels: + else: return 1.0 # identify luminance at threshold @@ -471,7 +472,7 @@ cdef class RGBPipeline2D(Pipeline2D): if peak_luminance == 0: return 1.0 - return 1 / peak_luminance + return 1.0 / peak_luminance @cython.boundscheck(False) @cython.wraparound(False) diff --git a/raysect/optical/observer/pipeline/spectral/__init__.pxd b/raysect/optical/observer/pipeline/spectral/__init__.pxd index 6e047e02..c2a80f6a 100644 --- a/raysect/optical/observer/pipeline/spectral/__init__.pxd +++ b/raysect/optical/observer/pipeline/spectral/__init__.pxd @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/pipeline/spectral/__init__.py b/raysect/optical/observer/pipeline/spectral/__init__.py index 2b1440cb..0d66c593 100644 --- a/raysect/optical/observer/pipeline/spectral/__init__.py +++ b/raysect/optical/observer/pipeline/spectral/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/pipeline/spectral/meson.build b/raysect/optical/observer/pipeline/spectral/meson.build new file mode 100644 index 00000000..b24d7a74 --- /dev/null +++ b/raysect/optical/observer/pipeline/spectral/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/observer/pipeline/spectral' + +# source files +py_files = ['__init__.py'] +pyx_files = ['power.pyx', 'radiance.pyx'] +pxd_files = ['__init__.pxd', 'power.pxd', 'radiance.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/optical/observer/pipeline/spectral/power.pxd b/raysect/optical/observer/pipeline/spectral/power.pxd index 6cfacef2..b73cf93d 100644 --- a/raysect/optical/observer/pipeline/spectral/power.pxd +++ b/raysect/optical/observer/pipeline/spectral/power.pxd @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/pipeline/spectral/power.pyx b/raysect/optical/observer/pipeline/spectral/power.pyx index 3a094816..36a726c2 100644 --- a/raysect/optical/observer/pipeline/spectral/power.pyx +++ b/raysect/optical/observer/pipeline/spectral/power.pyx @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/pipeline/spectral/radiance.pxd b/raysect/optical/observer/pipeline/spectral/radiance.pxd index 6c6034f5..9dfd285b 100644 --- a/raysect/optical/observer/pipeline/spectral/radiance.pxd +++ b/raysect/optical/observer/pipeline/spectral/radiance.pxd @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/pipeline/spectral/radiance.pyx b/raysect/optical/observer/pipeline/spectral/radiance.pyx index 6f4d32a7..daf0d41e 100644 --- a/raysect/optical/observer/pipeline/spectral/radiance.pyx +++ b/raysect/optical/observer/pipeline/spectral/radiance.pyx @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/sampler1d.pyx b/raysect/optical/observer/sampler1d.pyx index daac982a..12ea4790 100644 --- a/raysect/optical/observer/sampler1d.pyx +++ b/raysect/optical/observer/sampler1d.pyx @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/observer/sampler2d.pyx b/raysect/optical/observer/sampler2d.pyx index f61d0cce..61f4d198 100644 --- a/raysect/optical/observer/sampler2d.pyx +++ b/raysect/optical/observer/sampler2d.pyx @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -847,6 +847,8 @@ cdef class RGBAdaptiveSampler2D(FrameSampler2D): for c in range(3): if frame.mean_mv[x, y, c] > 0: pixel_normalised[c] = error[x, y, c] / frame.mean_mv[x, y, c] + else: + pixel_normalised[c] = 0.0 normalised_mv[x, y] = max(pixel_normalised[0], pixel_normalised[1], pixel_normalised[2]) # locate error value corresponding to fraction of frame to process diff --git a/raysect/optical/ray.pxd b/raysect/optical/ray.pxd index 38be8be7..176f1666 100644 --- a/raysect/optical/ray.pxd +++ b/raysect/optical/ray.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/ray.pyx b/raysect/optical/ray.pyx index d45e7588..78f07c64 100644 --- a/raysect/optical/ray.pyx +++ b/raysect/optical/ray.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -from libc.math cimport M_PI as PI, asin, cos +from libc.math cimport M_PI as PI, asin, cos, INFINITY from raysect.core cimport Intersection from raysect.core.math.random cimport probability @@ -39,9 +39,6 @@ from raysect.optical.spectrum cimport new_spectrum from raysect.optical.scenegraph cimport Primitive cimport cython -# cython doesn't have a built-in infinity constant, this compiles to +infinity -DEF INFINITY = 1e999 - cdef class Ray(CoreRay): """ diff --git a/raysect/optical/scenegraph/__init__.pxd b/raysect/optical/scenegraph/__init__.pxd index b37c869c..d7053c07 100644 --- a/raysect/optical/scenegraph/__init__.pxd +++ b/raysect/optical/scenegraph/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/scenegraph/__init__.py b/raysect/optical/scenegraph/__init__.py index 2cf9f357..1456a5fc 100644 --- a/raysect/optical/scenegraph/__init__.py +++ b/raysect/optical/scenegraph/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/scenegraph/meson.build b/raysect/optical/scenegraph/meson.build new file mode 100644 index 00000000..b0f90099 --- /dev/null +++ b/raysect/optical/scenegraph/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/optical/scenegraph' + +# source files +py_files = ['__init__.py'] +pyx_files = ['world.pyx'] +pxd_files = ['__init__.pxd', 'world.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/optical/scenegraph/world.pxd b/raysect/optical/scenegraph/world.pxd index 3421ca2f..0249c64d 100644 --- a/raysect/optical/scenegraph/world.pxd +++ b/raysect/optical/scenegraph/world.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -42,27 +42,18 @@ cdef class ImportanceManager: list _spheres cdef object _process_primitives(self, list primitives) - cdef object _calculate_cdf(self) - cdef tuple _pick_sphere(self) - cpdef Vector3D sample(self, Point3D origin) - cpdef double pdf(self, Point3D origin, Vector3D direction) - cpdef bint has_primitives(self) cdef class World(CoreWorld): - cdef: - ImportanceManager _importance + cdef ImportanceManager _importance cpdef build_importance(self, bint force=*) - cpdef Vector3D important_direction_sample(self, Point3D origin) - cpdef double important_direction_pdf(self, Point3D origin, Vector3D direction) - cpdef bint has_important_primitives(self) diff --git a/raysect/optical/scenegraph/world.pyx b/raysect/optical/scenegraph/world.pyx index 4d44cbb0..b7099a5a 100644 --- a/raysect/optical/scenegraph/world.pyx +++ b/raysect/optical/scenegraph/world.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/spectralfunction.pxd b/raysect/optical/spectralfunction.pxd index 82af135a..244ad4fd 100644 --- a/raysect/optical/spectralfunction.pxd +++ b/raysect/optical/spectralfunction.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/spectralfunction.pyx b/raysect/optical/spectralfunction.pyx index ea97de4c..003ecc95 100644 --- a/raysect/optical/spectralfunction.pyx +++ b/raysect/optical/spectralfunction.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/optical/spectrum.pxd b/raysect/optical/spectrum.pxd index a69d0655..7c465e56 100644 --- a/raysect/optical/spectrum.pxd +++ b/raysect/optical/spectrum.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,6 +32,7 @@ from raysect.optical.spectralfunction cimport SpectralFunction from numpy cimport ndarray + cdef class Spectrum(SpectralFunction): cdef: diff --git a/raysect/optical/spectrum.pyx b/raysect/optical/spectrum.pyx index 4111ab77..bb8ad335 100644 --- a/raysect/optical/spectrum.pyx +++ b/raysect/optical/spectrum.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -34,7 +34,7 @@ from raysect.core.math.cython cimport integrate, interpolate from numpy cimport PyArray_SimpleNew, PyArray_FILLWBYTE, NPY_FLOAT64, npy_intp, import_array # Plank's constant * speed of light in a vacuum -DEF CONSTANT_HC = 1.9864456832693028e-25 +cdef const double CONSTANT_HC = 1.9864456832693028e-25 # required by numpy c-api import_array() diff --git a/raysect/primitive/__init__.pxd b/raysect/primitive/__init__.pxd index 66ab91b8..cdcf2fae 100644 --- a/raysect/primitive/__init__.pxd +++ b/raysect/primitive/__init__.pxd @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -29,6 +29,7 @@ from raysect.primitive.box cimport Box from raysect.primitive.sphere cimport Sphere +from raysect.primitive.torus cimport Torus from raysect.primitive.cylinder cimport Cylinder from raysect.primitive.csg cimport Union, Intersect, Subtract from raysect.primitive.mesh cimport Mesh diff --git a/raysect/primitive/__init__.py b/raysect/primitive/__init__.py index 298643fc..fa3c6656 100644 --- a/raysect/primitive/__init__.py +++ b/raysect/primitive/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -28,6 +28,7 @@ # POSSIBILITY OF SUCH DAMAGE. from .box import Box +from .torus import Torus from .sphere import Sphere from .cylinder import Cylinder from .csg import Union, Intersect, Subtract diff --git a/raysect/primitive/box.pxd b/raysect/primitive/box.pxd index e09e5f0c..2b44fee6 100644 --- a/raysect/primitive/box.pxd +++ b/raysect/primitive/box.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/primitive/box.pyx b/raysect/primitive/box.pyx index 01d95d09..3f585b1b 100644 --- a/raysect/primitive/box.pyx +++ b/raysect/primitive/box.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -30,28 +30,27 @@ # POSSIBILITY OF SUCH DAMAGE. from raysect.core cimport new_point3d, Normal3D, new_normal3d, AffineMatrix3D, Material, new_intersection, BoundingBox3D -from libc.math cimport fabs +from libc.math cimport fabs, INFINITY cimport cython -# cython doesn't have a built-in infinity constant, this compiles to +infinity -DEF INFINITY = 1e999 - # bounding box is padded by a small amount to avoid numerical accuracy issues -DEF BOX_PADDING = 1e-9 +cdef const double BOX_PADDING = 1e-9 # additional ray distance to avoid re-hitting the same surface point -DEF EPSILON = 1e-9 - -# slab face enumeration -DEF NO_FACE = -1 -DEF LOWER_FACE = 0 -DEF UPPER_FACE = 1 - -# axis enumeration -DEF NO_AXIS = -1 -DEF X_AXIS = 0 -DEF Y_AXIS = 1 -DEF Z_AXIS = 2 +cdef const double EPSILON = 1e-9 + +cdef enum: + + # slab face enumeration + NO_FACE = -1 + LOWER_FACE = 0 + UPPER_FACE = 1 + + # axis enumeration + NO_AXIS = -1 + X_AXIS = 0 + Y_AXIS = 1 + Z_AXIS = 2 cdef class Box(Primitive): diff --git a/raysect/primitive/cone.pxd b/raysect/primitive/cone.pxd index e236e340..648b72fc 100644 --- a/raysect/primitive/cone.pxd +++ b/raysect/primitive/cone.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/primitive/cone.pyx b/raysect/primitive/cone.pyx index d1da1c9f..cff9592d 100644 --- a/raysect/primitive/cone.pyx +++ b/raysect/primitive/cone.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,22 +31,20 @@ from raysect.core cimport new_point3d, Point3D, new_normal3d, AffineMatrix3D, Material, new_intersection, BoundingBox3D from raysect.core.math.cython cimport solve_quadratic, swap_double, swap_int -from libc.math cimport sqrt +from libc.math cimport sqrt, INFINITY cimport cython -# cython doesn't have a built-in infinity constant, this compiles to +infinity -DEF INFINITY = 1e999 - # bounding box is padded by a small amount to avoid numerical accuracy issues -DEF BOX_PADDING = 1e-9 +cdef const double BOX_PADDING = 1e-9 # additional ray distance to avoid re-hitting the same surface point -DEF EPSILON = 1e-9 +cdef const double EPSILON = 1e-9 # object type enumeration -DEF NO_TYPE = -1 -DEF CONE = 0 -DEF BASE = 1 +cdef enum: + NO_TYPE = -1 + CONE = 0 + BASE = 1 cdef class Cone(Primitive): diff --git a/raysect/primitive/csg.pxd b/raysect/primitive/csg.pxd index a139cc12..794f6aea 100644 --- a/raysect/primitive/csg.pxd +++ b/raysect/primitive/csg.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/primitive/csg.pyx b/raysect/primitive/csg.pyx index 64ab3e9a..e32cbd29 100644 --- a/raysect/primitive/csg.pyx +++ b/raysect/primitive/csg.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,13 +31,12 @@ # TODO: add more advanced material handling +from libc.math cimport INFINITY + from raysect.core cimport _NodeBase, ChangeSignal, Material, new_ray, new_intersection, Point3D, AffineMatrix3D, BoundingBox3D # bounding box is padded by a small amount to avoid numerical accuracy issues -DEF BOX_PADDING = 1e-9 - -# cython doesn't have a built in infinity definition -DEF INFINITY = 1e999 +cdef const double BOX_PADDING = 1e-9 cdef class CSGPrimitive(Primitive): @@ -112,7 +111,7 @@ cdef class CSGPrimitive(Primitive): def primitive_b(self): """ Component primitive B of the compound CSG primitive. - + :rtype: Primitive """ return self._primitive_b.primitive diff --git a/raysect/primitive/cylinder.pxd b/raysect/primitive/cylinder.pxd index a1aa8f58..b7713a39 100644 --- a/raysect/primitive/cylinder.pxd +++ b/raysect/primitive/cylinder.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/primitive/cylinder.pyx b/raysect/primitive/cylinder.pyx index 9030e28d..f7ddd8d7 100644 --- a/raysect/primitive/cylinder.pyx +++ b/raysect/primitive/cylinder.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,27 +31,26 @@ from raysect.core cimport AffineMatrix3D, new_normal3d, new_point3d, new_vector3d, Material, new_intersection, BoundingBox3D from raysect.core.math.cython cimport solve_quadratic, swap_double -from libc.math cimport sqrt, fabs +from libc.math cimport sqrt, fabs, INFINITY cimport cython -# cython doesn't have a built-in infinity constant, this compiles to +infinity -DEF INFINITY = 1e999 - # bounding box is padded by a small amount to avoid numerical accuracy issues -DEF BOX_PADDING = 1e-9 +cdef const double BOX_PADDING = 1e-9 # additional ray distance to avoid re-hitting the same surface point -DEF EPSILON = 1e-9 +cdef const double EPSILON = 1e-9 + +cdef enum: -# object type enumeration -DEF NO_TYPE = -1 -DEF CYLINDER = 0 -DEF SLAB = 1 + # object type enumeration + NO_TYPE = -1 + CYLINDER = 0 + SLAB = 1 -# slab face enumeration -DEF NO_FACE = -1 -DEF LOWER_FACE = 0 -DEF UPPER_FACE = 1 + # slab face enumeration + NO_FACE = -1 + LOWER_FACE = 0 + UPPER_FACE = 1 cdef class Cylinder(Primitive): diff --git a/raysect/primitive/lens/meson.build b/raysect/primitive/lens/meson.build new file mode 100644 index 00000000..a53c2994 --- /dev/null +++ b/raysect/primitive/lens/meson.build @@ -0,0 +1,30 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/primitive/lens' + +# source files +py_files = ['__init__.py'] +pyx_files = ['spherical.pyx'] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('tests') diff --git a/raysect/primitive/lens/spherical.pyx b/raysect/primitive/lens/spherical.pyx index 31ade37b..4445b2d3 100644 --- a/raysect/primitive/lens/spherical.pyx +++ b/raysect/primitive/lens/spherical.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -40,7 +40,7 @@ from libc.math cimport sqrt Basic spherical lens primitives. """ -DEF PADDING = 0.000001 +cdef const double PADDING = 0.000001 cdef class BiConvex(EncapsulatedPrimitive): @@ -128,7 +128,7 @@ cdef class BiConvex(EncapsulatedPrimitive): cdef bint _is_short(self): """ - Do the facing spheres overlap sufficiently to build a lens using just their intersection? + Do the facing spheres overlap sufficiently to build a lens using just their intersection? """ cdef double available_thickness = min( @@ -326,7 +326,7 @@ cdef class PlanoConvex(EncapsulatedPrimitive): # attach to local root (performed in EncapsulatedPrimitive init) super().__init__(lens, parent, transform, material, name) - + cdef void _calc_geometry(self): cdef double radius, radius_sqr @@ -343,7 +343,7 @@ cdef class PlanoConvex(EncapsulatedPrimitive): cdef bint _is_short(self): """ - Does the front sphere have sufficient radius to build the lens with just an intersection? + Does the front sphere have sufficient radius to build the lens with just an intersection? """ cdef double available_thickness = 2 * (self.curvature - self.curve_thickness) @@ -548,7 +548,7 @@ cdef class Meniscus(EncapsulatedPrimitive): cdef bint _is_short(self): """ - Does the front sphere have sufficient radius to build the lens with just an intersection? + Does the front sphere have sufficient radius to build the lens with just an intersection? """ cdef double available_thickness = 2 * self.front_curvature - self.front_thickness diff --git a/raysect/primitive/lens/tests/meson.build b/raysect/primitive/lens/tests/meson.build new file mode 100644 index 00000000..04c5ead0 --- /dev/null +++ b/raysect/primitive/lens/tests/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/primitive/lens/tests' + +# source files +py_files = ['__init__.py', 'test_spherical.py'] +pyx_files = [] +pxd_files = [] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/primitive/lens/tests/test_spherical.py b/raysect/primitive/lens/tests/test_spherical.py index f8bd197e..8742ca8f 100644 --- a/raysect/primitive/lens/tests/test_spherical.py +++ b/raysect/primitive/lens/tests/test_spherical.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/primitive/mesh/__init__.pxd b/raysect/primitive/mesh/__init__.pxd index 7fa0f6bc..82461723 100644 --- a/raysect/primitive/mesh/__init__.pxd +++ b/raysect/primitive/mesh/__init__.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/primitive/mesh/__init__.py b/raysect/primitive/mesh/__init__.py index a0d71a23..75e86b5c 100644 --- a/raysect/primitive/mesh/__init__.py +++ b/raysect/primitive/mesh/__init__.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/primitive/mesh/mesh.pxd b/raysect/primitive/mesh/mesh.pxd index 3ef49448..7deb725a 100644 --- a/raysect/primitive/mesh/mesh.pxd +++ b/raysect/primitive/mesh/mesh.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -60,37 +60,21 @@ cdef class MeshData(KDTree3DCore): int32_t _i cpdef Point3D vertex(self, int index) - cpdef ndarray triangle(self, int index) - cpdef Normal3D vertex_normal(self, int index) - cpdef Normal3D face_normal(self, int index) - cdef object _filter_triangles(self) - cdef object _flip_normals(self) - cdef object _generate_face_normals(self) - cdef BoundingBox3D _generate_bounding_box(self, int32_t i) - cdef void _calc_rayspace_transform(self, Ray ray) - cdef bint _hit_triangle(self, int32_t i, Ray ray, float[4] hit_data) - cpdef Intersection calc_intersection(self, Ray ray) - cdef Normal3D _intersection_normal(self) - cpdef bint contains(self, Point3D p) - cpdef BoundingBox3D bounding_box(self, AffineMatrix3D to_world) - cdef uint8_t _read_uint8(self, object file) - cdef bint _read_bool(self, object file) - cdef double _read_float(self, object file) diff --git a/raysect/primitive/mesh/mesh.pyx b/raysect/primitive/mesh/mesh.pyx index ac27ddf7..048e21c2 100644 --- a/raysect/primitive/mesh/mesh.pyx +++ b/raysect/primitive/mesh/mesh.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -35,7 +35,7 @@ import struct from numpy import array, float32, int32, zeros from raysect.core cimport Primitive, AffineMatrix3D, Normal3D, new_normal3d, Point3D, new_point3d, Vector3D, new_vector3d, Material, Ray, new_ray, Intersection, new_intersection, BoundingBox3D, new_boundingbox3d from raysect.core.math.spatial cimport KDTree3DCore, Item3D -from libc.math cimport fabs +from libc.math cimport fabs, INFINITY from numpy cimport float32_t, int32_t, uint8_t from cpython.bytes cimport PyBytes_AsString cimport cython @@ -45,37 +45,41 @@ The ray-triangle intersection used for the Mesh primitive is an implementation o "Watertight Ray/Triangle Intersection", S.Woop, C.Benthin, I.Wald, Journal of Computer Graphics Techniques (2013), Vol.2, No. 1 """ -# cython doesn't have a built-in infinity constant, this compiles to +infinity -DEF INFINITY = 1e999 - # bounding box is padded by a small amount to avoid numerical accuracy issues -DEF BOX_PADDING = 1e-6 +cdef const double BOX_PADDING = 1e-6 # additional ray distance to avoid re-hitting the same surface point -DEF EPSILON = 1e-6 +cdef const double EPSILON = 1e-6 + +# constants +cdef enum: -# convenience defines -DEF X = 0 -DEF Y = 1 -DEF Z = 2 + # axis index + X = 0 + Y = 1 + Z = 2 -DEF U = 0 -DEF V = 1 -DEF W = 2 -DEF T = 3 + # intersection data + U = 0 + V = 1 + W = 2 + T = 3 -DEF V1 = 0 -DEF V2 = 1 -DEF V3 = 2 -DEF N1 = 3 -DEF N2 = 4 -DEF N3 = 5 + # vertex index + V1 = 0 + V2 = 1 + V3 = 2 -DEF NO_INTERSECTION = -1 + # normal index + N1 = 3 + N2 = 4 + N3 = 5 -# raysect mesh format constants -DEF RSM_VERSION_MAJOR = 1 -DEF RSM_VERSION_MINOR = 0 + NO_INTERSECTION = -1 + + # raysect mesh format constants + RSM_VERSION_MAJOR = 1 + RSM_VERSION_MINOR = 0 cdef class MeshIntersection(Intersection): @@ -279,9 +283,9 @@ cdef class MeshData(KDTree3DCore): cpdef Point3D vertex(self, int index): """ Returns the specified vertex. - + :param index: The vertex index. - :return: A Point3D object. + :return: A Point3D object. """ if index < 0 or index >= self.vertices_mv.shape[0]: @@ -296,13 +300,13 @@ cdef class MeshData(KDTree3DCore): cpdef ndarray triangle(self, int index): """ Returns the specified triangle. - - The returned data will either be a 3 or 6 element numpy array. The + + The returned data will either be a 3 or 6 element numpy array. The first three element are the triangle's vertex indices. If present, the last three elements are the triangle's vertex normal indices. - + :param index: The triangle index. - :return: A numpy array. + :return: A numpy array. """ if index < 0 or index >= self.vertices_mv.shape[0]: @@ -316,9 +320,9 @@ cdef class MeshData(KDTree3DCore): cpdef Normal3D vertex_normal(self, int index): """ Returns the specified vertex normal. - + :param index: The vertex normal's index. - :return: A Normal3D object. + :return: A Normal3D object. """ if self._vertex_normals is None: @@ -339,9 +343,9 @@ cdef class MeshData(KDTree3DCore): cpdef Normal3D face_normal(self, int index): """ Returns the specified face normal. - + :param index: The face normal's index. - :return: A Normal3D object. + :return: A Normal3D object. """ if index < 0 or index >= self.face_normals_mv.shape[0]: diff --git a/raysect/primitive/mesh/meson.build b/raysect/primitive/mesh/meson.build new file mode 100644 index 00000000..67ec049a --- /dev/null +++ b/raysect/primitive/mesh/meson.build @@ -0,0 +1,29 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/primitive/mesh' + +# source files +py_files = ['__init__.py', 'obj.py', 'ply.py', 'stl.py', 'vtk.py'] +pyx_files = ['mesh.pyx'] +pxd_files = ['__init__.pxd', 'mesh.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + diff --git a/raysect/primitive/mesh/obj.py b/raysect/primitive/mesh/obj.py index 1831dd65..e1ac904c 100644 --- a/raysect/primitive/mesh/obj.py +++ b/raysect/primitive/mesh/obj.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/primitive/mesh/ply.py b/raysect/primitive/mesh/ply.py index b11f7a7e..f5b8b8a3 100644 --- a/raysect/primitive/mesh/ply.py +++ b/raysect/primitive/mesh/ply.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/primitive/mesh/stl.py b/raysect/primitive/mesh/stl.py index 92f90db4..181d1bc0 100644 --- a/raysect/primitive/mesh/stl.py +++ b/raysect/primitive/mesh/stl.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/primitive/mesh/vtk.py b/raysect/primitive/mesh/vtk.py index 9012c26c..2f0ee17b 100644 --- a/raysect/primitive/mesh/vtk.py +++ b/raysect/primitive/mesh/vtk.py @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -102,7 +102,7 @@ def _load_ascii(cls, filename, scaling): @classmethod def _ascii_read_vertices(cls, f, scaling): - match = re.match("POINTS\s*([0-9]*)\s*float", f.readline().strip()) + match = re.match(r"POINTS\s*([0-9]*)\s*float", f.readline().strip()) if not match: raise RuntimeError("Unrecognised dataset encountered in vtk file.") num_points = int(match.group(1)) @@ -120,7 +120,7 @@ def _ascii_read_vertices(cls, f, scaling): @classmethod def _ascii_read_triangles(cls, f): - match = re.match("CELLS\s*([0-9]*)\s*([0-9]*)", f.readline()) + match = re.match(r"CELLS\s*([0-9]*)\s*([0-9]*)", f.readline()) if not match: raise RuntimeError("Unrecognised dataset encountered in vtk file.") num_triangles = int(match.group(1)) diff --git a/raysect/primitive/meson.build b/raysect/primitive/meson.build new file mode 100644 index 00000000..1f14a347 --- /dev/null +++ b/raysect/primitive/meson.build @@ -0,0 +1,31 @@ +# WARNING: This file is automatically generated by dev/generate_meson_files.py. +# The template file used to generate this file is dev/subdir-meson.build. + +target_path = 'raysect/primitive' + +# source files +py_files = ['__init__.py'] +pyx_files = ['box.pyx', 'cone.pyx', 'csg.pyx', 'cylinder.pyx', 'parabola.pyx', 'sphere.pyx', 'torus.pyx', 'utility.pyx'] +pxd_files = ['__init__.pxd', 'box.pxd', 'cone.pxd', 'csg.pxd', 'cylinder.pxd', 'parabola.pxd', 'sphere.pxd', 'torus.pxd', 'utility.pxd'] +data_files = [] + +# compile cython +foreach pyx_file: pyx_files + py.extension_module( + fs.replace_suffix(pyx_file, ''), + pyx_file, + dependencies: cython_dependencies, + install: true, + subdir: target_path, + cython_args: cython_args + ) +endforeach + +# add python, pxd and data files to the build +py.install_sources( + py_files + pxd_files + data_files, + subdir: target_path +) + +subdir('lens') +subdir('mesh') diff --git a/raysect/primitive/parabola.pxd b/raysect/primitive/parabola.pxd index 3eac4ba9..bbed0b57 100644 --- a/raysect/primitive/parabola.pxd +++ b/raysect/primitive/parabola.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/primitive/parabola.pyx b/raysect/primitive/parabola.pyx index 74f9a6e7..47cc257c 100644 --- a/raysect/primitive/parabola.pyx +++ b/raysect/primitive/parabola.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,23 +31,21 @@ from raysect.core cimport new_point3d, Point3D, new_normal3d, AffineMatrix3D, Material, new_intersection, BoundingBox3D from raysect.core.math.cython cimport solve_quadratic, swap_double, swap_int -from libc.math cimport sqrt +from libc.math cimport sqrt, INFINITY cimport cython -# cython doesn't have a built-in infinity constant, this compiles to +infinity -DEF INFINITY = 1e999 - # bounding box is padded by a small amount to avoid numerical accuracy issues -DEF BOX_PADDING = 1e-9 +cdef const double BOX_PADDING = 1e-9 # TODO - Perhaps should be calculated based on primitive scale # additional ray distance to avoid re-hitting the same surface point -DEF EPSILON = 1e-9 +cdef const double EPSILON = 1e-9 # object type enumeration -DEF NO_TYPE = -1 -DEF PARABOLA = 0 -DEF BASE = 1 +cdef enum: + NO_TYPE = -1 + PARABOLA = 0 + BASE = 1 cdef class Parabola(Primitive): diff --git a/raysect/primitive/sphere.pxd b/raysect/primitive/sphere.pxd index 18cbce8b..1f067a96 100644 --- a/raysect/primitive/sphere.pxd +++ b/raysect/primitive/sphere.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/raysect/primitive/sphere.pyx b/raysect/primitive/sphere.pyx index 081ea3e6..a1fa13f3 100644 --- a/raysect/primitive/sphere.pyx +++ b/raysect/primitive/sphere.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -35,11 +35,11 @@ from raysect.core.math.cython cimport solve_quadratic, swap_double # bounding box and sphere are padded by small amounts to avoid numerical accuracy issues -DEF BOX_PADDING = 1e-9 -DEF SPHERE_PADDING = 1.000000001 +cdef const double BOX_PADDING = 1e-9 +cdef const double SPHERE_PADDING = 1.000000001 # additional ray distance to avoid re-hitting the same surface point -DEF EPSILON = 1e-9 +cdef const double EPSILON = 1e-9 cdef class Sphere(Primitive): diff --git a/raysect/primitive/torus.pxd b/raysect/primitive/torus.pxd new file mode 100644 index 00000000..80de4d7c --- /dev/null +++ b/raysect/primitive/torus.pxd @@ -0,0 +1,46 @@ +# cython: language_level=3 + +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Raysect Project nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +from raysect.core cimport Primitive, Point3D, Vector3D, Ray, Intersection + +cdef class Torus(Primitive): + + cdef: + double _major_radius, _minor_radius + bint _further_intersection + int _next_t_index + int _num_t + double[4] _cached_t + Point3D _cached_origin + Vector3D _cached_direction + Ray _cached_ray + + cdef Intersection _generate_intersection(self, Ray ray, Point3D origin, Vector3D direction, double ray_distance) diff --git a/raysect/primitive/torus.pyx b/raysect/primitive/torus.pyx new file mode 100644 index 00000000..d839e05d --- /dev/null +++ b/raysect/primitive/torus.pyx @@ -0,0 +1,371 @@ +# cython: language_level=3 + +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the Raysect Project nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + + +from raysect.core cimport Material, new_intersection, BoundingBox3D, BoundingSphere3D, new_point3d, new_normal3d, Normal3D, AffineMatrix3D +from raysect.core.math.cython cimport solve_quartic, swap_double, sort_three_doubles, sort_four_doubles +from libc.math cimport hypot + + +# bounding box and sphere are padded by small amounts to avoid numerical accuracy issues +DEF BOX_PADDING = 1e-9 +DEF SPHERE_PADDING = 1.000000001 + +# additional ray distance to avoid re-hitting the same surface point +DEF EPSILON = 1e-9 + + +cdef class Torus(Primitive): + """ + A torus primitive. + + The torus is defined by major and minor radius. + The major radius is the distance from the center of the tube to the center of the torus. + The minor radius is the radius of the tube. + The center of the torus corresponds to the origin of the local coordinate system. + The axis of revolution coincides with the z-axis, and The center of the torus tube lies + on the x-y plane. + + :param float major_radius: Major radius of the torus in meters (default = 1.0). + :param float minor_radius: Minor radius of the torus in meters (default = 0.5). + :param Node parent: Scene-graph parent node or None (default = None). + :param AffineMatrix3D transform: An AffineMatrix3D defining the local coordinate system relative to the scene-graph parent (default = identity matrix). + :param Material material: A Material object defining the torus's material (default = None). + :param str name: A string specifying a user-friendly name for the torus (default = ""). + + :ivar float major_radius: The major radius of the torus in meters. + :ivar float minor_radius: The minor radius of the torus in meters. + + .. code-block:: pycon + + >>> from raysect.core import translate + >>> from raysect.primitive import Torus + >>> from raysect.optical import World + >>> from raysect.optical.material import UniformSurfaceEmitter + >>> from raysect.optical.library.spectra.colours import orange + >>> + >>> world = World() + >>> + >>> torus = Torus(1.0, 0.5, parent=world, transform=translate(3, 0, 0), + material=UniformSurfaceEmitter(orange), name="orange torus") + """ + + def __init__(self, double major_radius=1.0, double minor_radius=0.5, object parent=None, + AffineMatrix3D transform=None, Material material=None, str name=None): + + super().__init__(parent, transform, material, name) + + if major_radius < minor_radius or minor_radius < 0.0: + raise ValueError("Torus minor radius cannot be less than zero and greater than major radius.") + + self._major_radius = major_radius + self._minor_radius = minor_radius + + # initialise next intersection caching and control attributes + self._further_intersection = False + self._next_t_index = 0 + self._num_t = 0 + self._cached_origin = None + self._cached_direction = None + self._cached_ray = None + + @property + def major_radius(self): + """ + The major radius of this torus. + + :rtype: float + """ + return self._major_radius + + @major_radius.setter + def major_radius(self, double major_radius): + + # don't do anything if the value is unchanged + if major_radius == self._major_radius: + return + + if major_radius < 0.0: + raise ValueError("Torus major radius cannot be less than zero.") + if major_radius < self._minor_radius: + raise ValueError("Torus major radius cannot be less than minor radius.") + self._major_radius = major_radius + + # the next intersection cache has been invalidated by the major radius change + self._further_intersection = False + + # any geometry caching in the root node is now invalid, inform root + self.notify_geometry_change() + + @property + def minor_radius(self): + """ + The minor radius of this torus. + + :rtype: float + """ + return self._minor_radius + + @minor_radius.setter + def minor_radius(self, double minor_radius): + + # don't do anything if the value is unchanged + if minor_radius == self._minor_radius: + return + + if minor_radius < 0.0: + raise ValueError("Torus minor radius cannot be less than zero.") + if minor_radius > self._major_radius: + raise ValueError("Torus minor radius cannot be greater than major radius.") + self._minor_radius = minor_radius + + # the next intersection cache has been invalidated by the minor radius change + self._further_intersection = False + + # any geometry caching in the root node is now invalid, inform root + self.notify_geometry_change() + + cpdef Intersection hit(self, Ray ray): + + cdef: + Point3D origin + Vector3D direction + double sq_origin_xy, sq_direction_xy, sq_origin, sq_direction + double origin_direction_xy, origin_dot_direction, sq_r, sq_R, R2_r2 + double a, b, c, d, e, t_closest + double[4] t + int num, i + + # reset further intersection state + self._further_intersection = False + + # convert ray parameters to local space + origin = ray.origin.transform(self.to_local()) + direction = ray.direction.transform(self.to_local()) + + # calculate temporary values + sq_origin_xy = origin.x * origin.x + origin.y * origin.y + sq_direction_xy = direction.x * direction.x + direction.y * direction.y + + sq_origin = sq_origin_xy + origin.z * origin.z + sq_direction = sq_direction_xy + direction.z * direction.z + + origin_direction_xy = origin.x * direction.x + origin.y * direction.y + origin_dot_direction = origin_direction_xy + origin.z * direction.z + + sq_r = self._minor_radius * self._minor_radius + sq_R = self._major_radius * self._major_radius + R2_r2 = sq_R - sq_r + + # coefficients of quartic equation + a = sq_direction * sq_direction + b = 4.0 * sq_direction * origin_dot_direction + c = 2.0 * (2.0 * origin_dot_direction * origin_dot_direction + sq_direction * (sq_origin + R2_r2)) - 4.0 * sq_R * sq_direction_xy + d = 4.0 * origin_dot_direction * (sq_origin + R2_r2) - 8.0 * sq_R * origin_direction_xy + e = (sq_origin + R2_r2) * (sq_origin + R2_r2) - 4.0 * sq_R * sq_origin_xy + + # calculate intersection distances by solving the quartic equation + # ray misses if there are no real roots of the quartic + num = solve_quartic(a, b, c, d, e, &t[0], &t[1], &t[2], &t[3]) + + if num == 0: + return None + + elif num == 1: + # test the intersection points inside the ray search range [0, max_distance] + if t[0] > ray.max_distance or t[0] < 0.0: + return None + else: + t_closest = t[0] + + else: + # sorting solutions in each number of them + if num == 2: + # ensure t0 < t1 + if t[0] > t[1]: + swap_double(&t[0], &t[1]) + + # substitute the last value into undefined variables + t[2] = t[1] + t[3] = t[1] + + elif num == 3: + # ensure t0 < t1 < t2 + sort_three_doubles(&t[0], &t[1], &t[2]) + + # substitute the last value into undefined variables + t[3] = t[2] + + elif num == 4: + # ensure t0 < t1 < t2 < t3 + sort_four_doubles(&t[0], &t[1], &t[2], &t[3]) + else: + return None + + # test the intersection points inside the ray search range [0, max_distance] + if t[0] > ray.max_distance or t[3] < 0.0: + return None + + # cache the all intersection points + self._num_t = num + self._cached_t = t + + for i in range(num - 1): + if t[i] >= 0.0: + t_closest = t[i] + if t[i + 1] <= ray.max_distance: + self._further_intersection = True + self._next_t_index = i + 1 + self._cached_ray = ray + self._cached_origin = origin + self._cached_direction = direction + + return self._generate_intersection(ray, origin, direction, t_closest) + + if t[num - 1] <= ray.max_distance: + t_closest = t[num - 1] + else: + return None + + return self._generate_intersection(ray, origin, direction, t_closest) + + cpdef Intersection next_intersection(self): + + cdef: + double next_t + Intersection new_intersection + + if not self._further_intersection: + return None + + next_t = self._cached_t[self._next_t_index] + + # generate the next intersection. + new_intersection = self._generate_intersection( + self._cached_ray, + self._cached_origin, + self._cached_direction, + next_t, + ) + + # update the next intersection index + # if there are no more intersections, disable further intersection state + # and reset the next_t_index to 0 + if self._next_t_index < self._num_t - 1: + self._next_t_index += 1 + else: + self._further_intersection = False + self._next_t_index = 0 + + return new_intersection + + cdef Intersection _generate_intersection(self, Ray ray, Point3D origin, Vector3D direction, double ray_distance): + + cdef Point3D hit_point, inside_point, outside_point + cdef Normal3D normal + cdef double alpha, delta_x, delta_y, delta_z + cdef bint exiting + + # point of surface intersection in local space + hit_point = new_point3d(origin.x + ray_distance * direction.x, + origin.y + ray_distance * direction.y, + origin.z + ray_distance * direction.z) + + # normal is normalised vector from torus tube centre to hit_point + alpha = self._major_radius / hypot(hit_point.x, hit_point.y) + normal = new_normal3d((1.0 - alpha) * hit_point.x, (1.0 - alpha) * hit_point.y, hit_point.z) + normal = normal.normalise() + + # calculate points inside and outside of surface for daughter rays to + # spawn from - these points are displaced from the surface to avoid + # re-hitting the same surface + delta_x = EPSILON * normal.x + delta_y = EPSILON * normal.y + delta_z = EPSILON * normal.z + + inside_point = new_point3d(hit_point.x - delta_x, hit_point.y - delta_y, hit_point.z - delta_z) + outside_point = new_point3d(hit_point.x + delta_x, hit_point.y + delta_y, hit_point.z + delta_z) + + # is ray exiting surface + exiting = direction.dot(normal) >= 0.0 + + return new_intersection(ray, ray_distance, self, hit_point, inside_point, outside_point, + normal, exiting, self.to_local(), self.to_root()) + + cpdef bint contains(self, Point3D point) except -1: + + cdef Point3D local_point + cdef double discriminant, distance_xy, distance_sqr, sq_R, R2_r2 + + # convert world space point to local space + local_point = point.transform(self.to_local()) + + # calculate the interior discriminant + distance_xy = local_point.x * local_point.x + local_point.y * local_point.y + distance_sqr = distance_xy + local_point.z * local_point.z + sq_R = self._major_radius * self._major_radius + R2_r2 = sq_R - self._minor_radius * self._minor_radius + discriminant = distance_sqr * distance_sqr + 2.0 * distance_sqr * R2_r2 + R2_r2 * R2_r2 - 4.0 * sq_R * distance_xy + + # point is outside torus if discriminant is greater than 0 + return discriminant <= 0.0 + + cpdef BoundingBox3D bounding_box(self): + + cdef: + double extent + list points + Point3D point + BoundingBox3D box + + box = BoundingBox3D() + + # calculate local bounds + extent = self._major_radius + self._minor_radius + BOX_PADDING + box.lower = new_point3d(-extent, -extent, -self._minor_radius - BOX_PADDING) + box.upper = new_point3d(extent, extent, self._minor_radius + BOX_PADDING) + + # obtain local space vertices + points = box.vertices() + + # convert points to world space + box = BoundingBox3D() + for point in points: + box.extend(point.transform(self.to_root())) + + return box + + cpdef BoundingSphere3D bounding_sphere(self): + cdef Point3D centre = new_point3d(0, 0, 0).transform(self.to_root()) + return BoundingSphere3D(centre, (self._major_radius + self._minor_radius) * SPHERE_PADDING) + + cpdef object instance(self, object parent=None, AffineMatrix3D transform=None, Material material=None, str name=None): + return Torus(self._major_radius, self._minor_radius, parent, transform, material, name) \ No newline at end of file diff --git a/raysect/primitive/utility.pxd b/raysect/primitive/utility.pxd index d4a9b1f3..cce6cc05 100644 --- a/raysect/primitive/utility.pxd +++ b/raysect/primitive/utility.pxd @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -38,9 +38,6 @@ cdef class EncapsulatedPrimitive(Primitive): Primitive _primitive cpdef Intersection hit(self, Ray ray) - cpdef Intersection next_intersection(self) - cpdef bint contains(self, Point3D p) except -1 - cpdef BoundingBox3D bounding_box(self) diff --git a/raysect/primitive/utility.pyx b/raysect/primitive/utility.pyx index b3060ff6..7ca8a1e4 100644 --- a/raysect/primitive/utility.pyx +++ b/raysect/primitive/utility.pyx @@ -1,6 +1,6 @@ # cython: language_level=3 -# Copyright (c) 2014-2023, Dr Alex Meakins, Raysect Project +# Copyright (c) 2014-2025, Dr Alex Meakins, Raysect Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/setup.py b/setup.py deleted file mode 100644 index a02a8973..00000000 --- a/setup.py +++ /dev/null @@ -1,122 +0,0 @@ -from setuptools import setup, find_packages, Extension -from setuptools.command.build_ext import build_ext as _build_ext -import sys -import numpy -import os -import os.path as path -import multiprocessing - -multiprocessing.set_start_method('fork') - -use_cython = True -force = False -profile = False -line_profile = False -annotate = False - -if "--skip-cython" in sys.argv: - use_cython = False - del sys.argv[sys.argv.index("--skip-cython")] - -if "--force" in sys.argv: - force = True - del sys.argv[sys.argv.index("--force")] - -if "--profile" in sys.argv: - profile = True - del sys.argv[sys.argv.index("--profile")] - -if "--line-profile" in sys.argv: - line_profile = True - del sys.argv[sys.argv.index("--line-profile")] - -if "--annotate" in sys.argv: - annotate = True - sys.argv.remove("--annotate") - -source_paths = ['raysect', 'demos'] -compilation_includes = [".", numpy.get_include()] -compilation_args = ['-O3'] -cython_directives = { - # 'auto_pickle': True, - 'language_level': 3 -} -setup_path = path.dirname(path.abspath(__file__)) - -if line_profile: - compilation_args.append("-DCYTHON_TRACE=1") - compilation_args.append("-DCYTHON_TRACE_NOGIL=1") - cython_directives["linetrace"] = True - -if use_cython: - - from Cython.Build import cythonize - - # build .pyx extension list - extensions = [] - for package in source_paths: - for root, dirs, files in os.walk(path.join(setup_path, package)): - for file in files: - if path.splitext(file)[1] == ".pyx": - pyx_file = path.relpath(path.join(root, file), setup_path) - module = path.splitext(pyx_file)[0].replace("/", ".") - extensions.append(Extension(module, [pyx_file], include_dirs=compilation_includes, extra_compile_args=compilation_args),) - - if profile: - cython_directives["profile"] = True - - # generate .c files from .pyx - extensions = cythonize(extensions, nthreads=multiprocessing.cpu_count(), force=force, compiler_directives=cython_directives, annotate=annotate) - -else: - - # build .c extension list - extensions = [] - for package in source_paths: - for root, dirs, files in os.walk(path.join(setup_path, package)): - for file in files: - if path.splitext(file)[1] == ".c": - c_file = path.relpath(path.join(root, file), setup_path) - module = path.splitext(c_file)[0].replace("/", ".") - extensions.append(Extension(module, [c_file], include_dirs=compilation_includes, extra_compile_args=compilation_args),) - -# parse the package version number -with open(path.join(path.dirname(__file__), 'raysect/VERSION')) as version_file: - version = version_file.read().strip() - -# Use multiple processes by default for building extensions -class build_ext(_build_ext): - def finalize_options(self): - super().finalize_options() - if self.parallel is None: - nproc = int(os.getenv("RAYSECT_BUILD_JOBS", str(multiprocessing.cpu_count()))) - self.parallel = nproc - -setup( - name="raysect", - version=version, - url="http://www.raysect.org", - author="Dr Alex Meakins et al.", - author_email="developers@raysect.org", - description='A Ray-tracing Framework for Science and Engineering', - license="BSD", - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Science/Research", - "Intended Audience :: Education", - "Intended Audience :: Developers", - "License :: OSI Approved :: BSD License", - "Natural Language :: English", - "Operating System :: POSIX :: Linux", - "Programming Language :: Cython", - "Programming Language :: Python :: 3", - "Topic :: Multimedia :: Graphics :: 3D Rendering", - "Topic :: Scientific/Engineering :: Physics" - ], - install_requires=['numpy', 'matplotlib'], - packages=find_packages(), - include_package_data=True, - zip_safe= False, - ext_modules=extensions, - cmdclass={"build_ext": build_ext}, -)