-
-
Notifications
You must be signed in to change notification settings - Fork 124
Description
Checklist
- I have searched the existing issues and discussions for a similar question or feature request.
- I have read the documentation and tried to find an answer there.
- I am using the latest version of Optiland.
- I have included all necessary context.
Feature Request
This feature request description is co-authored with copilot.
Is your feature request related to a problem? Please describe.
Currently, optiland requires users to build optical systems by manually defining and managing individual surfaces with explicit indexing. While this low-level approach provides fine-grained control, it creates several challenges:
- Verbose and error-prone code: Defining a simple lens requires manually creating two surfaces with correct indices and managing the relationship between them
- Reduced code readability: It's not immediately clear what optical elements a system contains by looking at surface definitions
- No abstraction for complete optical elements: Common components like doublets, mirrors, or prisms must be manually constructed from raw surfaces every time
- Harder positioning and transformations of surface groups: Requires adding coordinate breaks
- Cumbersome index manipulation: Need to keep track manually of surface indexes.
- No edge surfaces definition: This could make it less straight forward to implement non-sequential ray tracing.
Describe the solution you'd like
Introduce a component-based API that provides high-level abstractions for complete optical elements (lenses, mirrors, doublets, triplets, etc.) alongside the existing surface-based API. This new system would:
Core Architecture:
-
OpticalComponent base class: Foundation for all optical components with local coordinate systems for 3D positioning and rotation
-
Component library: Pre-built implementations of common optical elements (Singlet/Lens, Doublet, Triplet, Mirror, BeamSplitter, Window, Prism, Grating, Eye, ...)
-
ComponentGroup manager: Handles collections of components and converts them to surface sequences for ray tracing
Seamless integration: Should work alongside existing surface-based API with no breaking changes.
Key Features:
- Intuitive design workflow: Work with complete optical elements instead of raw surfaces
- Automatic index management: No need to manually track surface indices ( for sequential we can build the
- 3D coordinate systems: Each component has position and rotation for easy placement
- Encapsulation: Components internally manage their surfaces and relationships
- Composition: Complex components (like Doublet) composed from simpler ones (Singlets)
- Backward compatible: Existing surface-based code continues to work unchanged
- Example API:
from optiland import optic
from optiland.components import Lens, Doublet, Mirror
# Create optical system
system = optic.Optic(name="Camera Lens")
# Add components with intuitive parameters
lens1 = Lens(
radius1=50.0, # Front surface radius
radius2=-50.0, # Back surface radius
thickness=5.0, # Center thickness
material="N-BK7", # Glass material
diameter=25.0, # Clear aperture
position=(0, 0, 0) # 3D position
)
# Add achromatic doublet
doublet = Doublet(
radius1=62.0,
radius2=-45.0,
radius3=-129.0,
thickness1=6.0,
thickness2=2.5,
material1="N-BK7", # Crown glass
material2="N-SF5", # Flint glass
diameter=25.4,
position=(0, 0, 10) # 10mm after lens1
)
# Add folding mirror
mirror = Mirror(
radius=100.0,
diameter=30.0,
position=(0, 0, 50),
rotation=(0, 45, 0) # 45° tilt
)
# Add to system (no index management!)
system.add_component(lens1)
system.add_component(doublet)
system.add_component(mirror)
# Configure and trace as usual
system.set_aperture(aperture_type="EPD", value=20.0)
system.set_field_type(field_type="angle")
system.add_field(y=0)
system.add_wavelength(value=0.588, is_primary=True)
# Surfaces automatically generated for ray tracing
system.build_surface_group_from_components()
# Access component properties
print(f"Lens focal length: {lens1.focal_length:.2f} mm")Describe alternatives you've considered
Keep only surface-based API
Additional context
- Backward compatibility: The surface-based API remains unchanged and fully supported. Users can gradually adopt components or mix both approaches.
- Easier implementation of features such as ISO 10110 Drawing Generator #458, and any other operation that targets optical components not surfaces.