Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow explicit segment count limitation #8

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 33 additions & 38 deletions inkscape_raytracing/raytracing/world.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,18 @@ class OpticalObject(NamedTuple):
material: OpticMaterial


class Tip(NamedTuple):
beam: Ray
rays: List


@dataclass
class World:
"""Stores a scene and computes the interaction with a ray"""

objects: Optional[list[OpticalObject]] = field(default_factory=list)
# default recursion depth can be changed, but should not exceed
# system recursion limit.
max_recursion_depth: Optional[int] = 500
max_segment_count: Optional[int] = 500
show_warning: Optional[bool] = True

def add(self, obj: OpticalObject):
self.objects.append(obj)
Expand Down Expand Up @@ -56,38 +60,29 @@ def first_hit(self, ray: Ray) -> Tuple[ShadeRec, OpticMaterial]:
return result, material

def propagate_beams(self, seed):
return self._propagate_beams([[seed]], 0)

def _propagate_beams(self, beams: List[List[Ray]], depth) -> List[List[Ray]]:
"""Computes the propagation of beams in the system

:return: List of all the beam paths generated by these seeds.
It is stored as
[path0[Ray0, Ray1, ...], path1[...], ...].
Each path is a list of successive rays having each traveled a
given distance.
:raise: warning if recursion depth hits a limit.
"""

if depth >= self.max_recursion_depth:
err_msg = (
f"Maximal recursion depth exceeded ({self.max_recursion_depth})."
"It is likely that not all beams have been rendered."
)
warnings.warn(err_msg)
return beams
else:
new_beams = list()
for index, beam in enumerate(beams):
ray = beam[-1]
if ray.travel <= 0:
shade, material = self.first_hit(ray)
new_seeds = material.generated_beams(ray, shade)
beams[index][-1] = Ray(ray.origin, ray.direction, shade.travel_dist)
if len(new_seeds) == 0:
new_beams.append(beams[index])
for seed in new_seeds:
generated_beams = self._propagate_beams([[seed]], depth + 1)
for new_beam in generated_beams:
new_beams.append(beams[index] + new_beam)
return new_beams
initial_beam = []
beams = [initial_beam]
tips = [Tip(seed, initial_beam)]
while len(tips):
tip = tips.pop(0)
if len(tip.rays) >= self.max_segment_count:
err_msg = (
f"Maximal segment count exceeded ({self.max_segment_count})."
"It is likely that not all beams have been rendered."
)
tips = []
if self.show_warning:
warnings.warn(err_msg)
else:
shade, material = self.first_hit(tip.beam)
new_seeds = material.generated_beams(tip.beam, shade)
ray = Ray(tip.beam.origin, tip.beam.direction, shade.travel_dist)
tip.rays.append(ray)
rays = [tip.rays] if len(new_seeds) == 1 else [tip.rays, *[[*tip.rays] for i in range(len(new_seeds)-1)]]
for index, seed in enumerate(new_seeds):
tips.append(Tip(seed, rays[index]))
rays.pop(0)
for r in rays:
beams.append(r)

return beams
2 changes: 2 additions & 0 deletions inkscape_raytracing/render.inx
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@
<script>
<command location="inx" interpreter="python">render.py</command>
</script>
<param name="max_segment_count" type="int" gui-text="Maximum segment count:" max="10000" indent="1">500</param>
<param name="show_iteration_warning" type="bool" gui-text="Display iteration limit reached warning">true</param>
</inkscape-extension>

6 changes: 6 additions & 0 deletions inkscape_raytracing/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,16 @@ def __init__(self):
self.world = World()
self.beam_seeds: list[BeamSeed] = list()

def add_arguments(self, pars):
pars.add_argument("--max_segment_count", type=int)
pars.add_argument("--show_iteration_warning", type=str)

def effect(self) -> None:
"""
Loads the objects and outputs a svg with the beams after propagation
"""
self.world.max_segment_count = self.options.max_segment_count
self.world.show_warning = self.options.show_iteration_warning == 'true'

# Can't set the border earlier because self.svg is not yet defined
self.document_border = self.get_document_borders_as_beamdump()
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "inkscape-raytracing"
version = "1.1"
version = "1.2.0"
description = "An extension for Inkscape that makes it easier to draw optical diagrams."
authors = ["Your Name <[email protected]>"]
license = "GPL3"
Expand Down