def creation(scene, creation_type): if creation_type == "direct creation": # une region m1 = Point(70, 60) # refractive index for rp1 n = 1.5 rp1 = regions.Polycurve(n=n, scene=scene) rp1.start(m1) m2 = Point(70, 190) rp1.add_line(m2) m3 = Point(110, 190) rp1.add_line(m3) m4 = Point(110, 60) tg4 = Vector(10, -20) #rp1.add_line(m4) rp1.add_arc(m4, tg4) rp1.close() del rp1 p0 = Point(10, 20) u0 = Vector(108, 50) s0 = 3 line0 = Line(p0, u0) source1 = sources.SingleRay(line0=line0, s0=s0, scene=scene) del line0 del source1 gc.collect() # !! comment ou this line => no crash !! scene.propagate() elif creation_type == "scene.load": filename = 'tests/shifted_polycurves+single_ray.geoptics' with open(filename, 'r') as f: config = yaml.safe_load(stream=f) logger.debug("config: {}".format(config)) scene.clear() scene_config = config['Scene'] scene.config = scene_config #gui.scene.load(config['Scene']) scene.propagate() elif creation_type == "load individually": filename = 'tests/shifted_polycurves+single_ray.geoptics' with open(filename, 'r') as f: config = yaml.safe_load(stream=f) config_rp1 = config['Scene']['Regions'][0] logger.debug("config: {}".format(config_rp1)) rp1 = regions.Polycurve.from_config(config=config_rp1, scene=scene) del rp1 #gc.collect() #qapp.processEvents() config_source1 = config['Scene']['Sources'][0] logger.debug("{}".format(config_source1['rays'][0])) source1 = sources.SingleRay.from_config( # noqa: F841 config=config_source1, scene=scene) logger.debug("{}".format(scene.sources)) del source1 gc.collect() #qapp.processEvents() # !! comment out this line => no crash !! scene.propagate()
def __init__(self, p=None, u=None): if p is None: self.p = Point(x=0, y=0) else: self.p = p.copy() if u is None: self.u = Vector(x=1, y=0) else: self.u = u.copy()
def test_orientations(): # left to right, arc above segment arc = Arc(Point(10, 20), Point(50, 30), Vector(10, 20)) assert arc.ccw is False line = Line(Point(30, 10), Vector(10, 30)) intersections = arc.intersection(line, sign_of_s=1) assert len(intersections) == 1 # right to left, arc above segment arc = Arc(Point(50, 30), Point(10, 20), Vector(-10, 20)) assert arc.ccw is True line = Line(Point(30, 10), Vector(10, 30)) intersections = arc.intersection(line, sign_of_s=1) assert len(intersections) == 1 # left to right, arc below segment arc = Arc(Point(10, 20), Point(50, 30), Vector(10, -20)) assert arc.ccw is True line = Line(Point(30, 10), Vector(10, -30)) intersections = arc.intersection(line, sign_of_s=1) assert len(intersections) == 1 # right to left, arc below segment arc = Arc(Point(50, 30), Point(10, 20), Vector(-10, -20)) assert arc.ccw is False line = Line(Point(30, 20), Vector(10, -30)) intersections = arc.intersection(line, sign_of_s=1) assert len(intersections) == 1
def interpolate(line_start, line_end, x): """Interpolated line. The returned line is interpolated between two given lines, going ccw from `line_start` to `line_end`. The interpolation is done on `Line.p` and on the `Line.u` angle. Args: line_start (Line): The starting line. line_end (Line): The ending line. x (float): the fraction, between 0.0 (starting line) and 1.0 (ending line). Returns: Line: Interpolated line. """ p = (1 - x) * line_start.p + x * line_end.p angle_start = line_start.u.theta_x() angle_end = line_end.u.theta_x() if angle_end < angle_start: # we want to go ccw from start to end angle_end += 2 * pi angle = (1 - x) * angle_start + x * angle_end u = Vector(x=cos(angle), y=sin(angle)) return Line(p=p, u=u)
def from_config(cls, config, scene=None, tag=None): """Alternate constructor. Args: config (dict): Configuration dictionary Returns: :class:`.Polycurve`: new Polycurve instance """ if tag is None: tag = config.get('tag') region = cls(scene=scene, tag=tag) curves_config = config['curves'] M_start = Point.from_config(curves_config[0]['M1']) region.start(M_start) region.tag = config.get('tag') region.n = config['n'] for curve_config in curves_config: cls = curve_config['Class'] if cls == 'Segment': M_next = Point.from_config(curve_config['M2']) region.add_line(M_next) elif cls == 'Arc': M_next = Point.from_config(curve_config['M2']) tangent = Vector.from_config(curve_config['tangent']) region.add_arc(M_next, tangent) else: raise (NotImplementedError) # normally, the stored polycurves are already closed # (the last point is equal to the first one) # no need for a final close() return region
def test_create_line_handle(scene, parent_item): p = Point(10, 20) u = Vector(30, 60) line0 = Line(p, u) # The initial position should be free, even with move restrictions on scene.g.move_restrictions_on = True lh = LineHandle(line0, parent=parent_item) assert lh.h_p0.pos().x() == 10 assert lh.h_p0.pos().y() == 20
def scene_polycurve_beam_singleray(scene): """Return a Scene with Polycurve region + Beam and SingleRay sources.""" from geoptics.elements.vector import Point, Vector n = 1.5 m1 = Point(70, 60) # rp1 cls = scene.class_map['Regions']['Polycurve'] rp1 = cls(n=n, scene=scene) rp1.start(m1) m2 = Point(70, 190) rp1.add_line(m2) m3 = Point(110, 190) rp1.add_line(m3) m4 = Point(110, 60) tg4 = Vector(10, -20) #rp1.add_line(m4) rp1.add_arc(m4, tg4) rp1.close() return scene
def from_config(cls, config): """Alternate constructor. Args: config (dict): Configuration dictionary Returns: Line: new Line instance Examples: >>> from geoptics.elements.vector import Point, Vector >>> p = Point(10, 20) >>> u = Vector(30, 60) >>> line1 = Line(p, u) >>> config = line1.config >>> line2 = Line.from_config(config) >>> line2.config == config True """ p = Point.from_config(config['p']) u = Vector.from_config(config['u']) return cls(p, u)
def line(): """Return a generic Line.""" p = Point(10, 20) u = Vector(30, 60) return Line(p, u)
scene = gui.scene # refractive index for rp1 n = 1.5 # rp1 rp1 = geoptics.guis.qt.regions.Polycurve(n=n, scene=scene) m1 = Point(70, 60) rp1.start(m1) m2 = Point(70, 190) rp1.add_line(m2) m3 = Point(110, 190) rp1.add_line(m3) m4 = Point(110, 60) tg4 = Vector(10, -20) rp1.add_arc(m4, tg4) rp1.close() # tracé d'un rayon p0 = Point(10, 50) u0 = Vector(108, 0) s0 = 3 n0 = 1.0 p1 = Point(10, 80) u1 = Vector(108, 0) source2 = QtBeamOPL(line_start=Line(p0, u0), line_end=Line(p1, u1), s_start=100, s_end=100,
def vector(): """Return a generic Vector.""" return Vector(30, 60)
class Line(object): """Line defined by a point `p` and a direction vector `u`. Args: p (Point): Reference point belonging to the line u (Vector): Direction vector """ def __init__(self, p=None, u=None): if p is None: self.p = Point(x=0, y=0) else: self.p = p.copy() if u is None: self.u = Vector(x=1, y=0) else: self.u = u.copy() @property def config(self): # noqa: D401 """Configuration dictionary.""" return { 'p': self.p.config, 'u': self.u.config, } def copy(self): """Return an independent copy.""" return Line(self.p, self.u) @classmethod def from_config(cls, config): """Alternate constructor. Args: config (dict): Configuration dictionary Returns: Line: new Line instance Examples: >>> from geoptics.elements.vector import Point, Vector >>> p = Point(10, 20) >>> u = Vector(30, 60) >>> line1 = Line(p, u) >>> config = line1.config >>> line2 = Line.from_config(config) >>> line2.config == config True """ p = Point.from_config(config['p']) u = Vector.from_config(config['u']) return cls(p, u) def normal(self, normalized=False): """Return a vector orthogonal to the line. Args: normalized (bool): if True, return a unit vector. Returns: :class:`.Vector` """ normal = self.u.normal(normalized) return normal def tangent(self, normalized=False): """Return a tangent vector to the line. For a line, this is basically `u` itself. Args: normalized (bool): if True, return a unit vector. Returns: :class:`.Vector` """ if normalized: tangent = self.u.copy() tangent.normalize() return tangent else: return self.u.copy() def intersection(self, other, sign_of_s=0): """Intersections of the line with another line. Args: other (Line): another line. sign_of_s (float): if ``sign_of_s !=0``, consider other as a half line, and search for intersections with `s` having the same sign as `sign_of_s`. Returns: :obj:`list` of :class:`Intersection`: list either empty (no intersection), or holding a single intersection. This is done for consistency with other elements that can have multiple intersections with a line. """ if isinstance(other, Line): if other.u.colinear(self.u): result = [] else: s = (((self.p.x - other.p.x) * self.u.y - (self.p.y - other.p.y) * self.u.x) / (other.u.x * self.u.y - other.u.y * self.u.x)) if (sign_of_s == 0 and s != 0) or (s * sign_of_s > 0): Mi = Point(other.p.x + s * other.u.x, other.p.y + s * other.u.y) eN = self.normal(normalized=True) eT = self.tangent(normalized=True) result = [Intersection(Mi, s, eN, eT)] else: result = [] else: raise NotImplementedError( "intersection between Line and {}".format(type(other))) return result @staticmethod def interpolate(line_start, line_end, x): """Interpolated line. The returned line is interpolated between two given lines, going ccw from `line_start` to `line_end`. The interpolation is done on `Line.p` and on the `Line.u` angle. Args: line_start (Line): The starting line. line_end (Line): The ending line. x (float): the fraction, between 0.0 (starting line) and 1.0 (ending line). Returns: Line: Interpolated line. """ p = (1 - x) * line_start.p + x * line_end.p angle_start = line_start.u.theta_x() angle_end = line_end.u.theta_x() if angle_end < angle_start: # we want to go ccw from start to end angle_end += 2 * pi angle = (1 - x) * angle_start + x * angle_end u = Vector(x=cos(angle), y=sin(angle)) return Line(p=p, u=u) def point(self, s): """Return the :class:`.Point` at the position ``p + s * u``.""" return Point(self.p.x + s * self.u.x, self.p.y + s * self.u.y) def __repr__(self): return "Line({p}, {u})".format(**vars(self)) def translate(self, **kwargs): """Translate the starting point. Same syntax and same side effects as :py:func:`geoptics.elements.vector.Point.translate` Likewise, it is possible to insert a ``.copy()`` to avoid side-effects. return `self` for convenience """ self.p.translate(**kwargs) return self
scene = gui.scene # refractive index for rp1 n = 1.5 # rp1 rp1 = regions.Polycurve(n=n, scene=scene) m1 = Point(70, 60) rp1.start(m1) m2 = Point(70, 190) rp1.add_line(m2) m3 = Point(110, 190) rp1.add_line(m3) m4 = Point(110, 60) tg4 = Vector(10, -20) #rp1.add_line(m4) rp1.add_arc(m4, tg4) rp1.close() #rp1.translate(Vector(0, 100)) #rp2 = regions.Polycurve(n, scene=scene) #rp2.start(Point(121.0, 38.0)) #rp2.add_line(Point(121.0, 168.0)) #rp2.add_line(Point(161.0, 168.0)) #rp2.add_line(Point(161.0, 38.0)) #rp2.close() # tracé d'un rayon p0 = Point(10, 20)
def arc(): """Return a generic Arc.""" M1 = Point(10, 20) M2 = Point(50, 30) tangent = Vector(10, 20) return Arc(M1, M2, tangent)