Source code for geoptics.elements.segment

# -*- coding: utf-8 -*-

# Copyright (C) 2014 ederag <edera@gmx.fr>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GeOptics; see the file LICENSE.txt.  If not, see
# <http://www.gnu.org/licenses/>.


"""Define a geometric Segment [M1, M2]."""


from geoptics.elements.vector import Vector_M1M2

from .line import Line


[docs]class Segment(object): """Segment defined by its two ends: M1 et M2. Args: M1 (Point): first end M2 (Point): second end """ def __init__(self, M1, M2): self.M1 = M1.copy() self.M2 = M2.copy() @property def config(self): # noqa: D401 """Configuration dictionary.""" return {'Class': 'Segment', 'M1': self.M1.config, 'M2': self.M2.config, }
[docs] def normal(self, normalized=False): """Return a normal to the segment. Args: normalized (bool): if True, return a unit vector. Returns: :class:`~.elements.vector.Vector` """ return Vector_M1M2(self.M1, self.M2).normal(normalized=normalized)
[docs] def middle(self): """Return the middle of the segment.""" return (self.M1 + self.M2) * 0.5
[docs] def intersection(self, other, sign_of_s=0): """Intersections of the segment with another element. Args: other (Line): another element (as of v0.18, it must be a Line) sign_of_s (int): if `sign_of_s !=0`, consider other as a half line. i.e. `s_other` must have the same sign as `sign_of_s` or intersection will be empty Returns: :obj:`list` of :class:`.Intersection`: list of intersections """ if isinstance(other, Line): result = Line(self.M1, Vector_M1M2(self.M1, self.M2) ).intersection(other, sign_of_s) if not result: # no intersection return [] else: # there should be only one intersection # split the sequence unpacking in two chunks for # kdevelop semantic analysis intersection, = result Mi, s, eN, eT = intersection if abs(self.M2.x - self.M1.x) > abs(self.M2.y - self.M1.y): # M1M2 closer to x axis if (self.M2.x > self.M1.x): # M2 to the right of M1 if (Mi.x < self.M1.x) or (Mi.x > self.M2.x): # outside return [] else: # M2 to the left of M1 if (Mi.x < self.M2.x) or (Mi.x > self.M1.x): # outside return [] else: # M1M2 closer to y axis if (self.M2.y > self.M1.y): # M2 above M1 if (Mi.y < self.M1.y) or (Mi.y > self.M2.y): # outside return [] else: # M2 below M1 if (Mi.y < self.M2.y) or (Mi.y > self.M1.y): # outside return [] else: raise NotImplementedError( "intersection between Line and {}".format(type(other)) ) return result
def __repr__(self): return "Segment({M1}, {M2})".format(**vars(self))
[docs] def translate(self, **kwargs): """Translate the segment as a whole. 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. FIXME: :meth:`copy()` not implemented yet... return `self` for convenience """ self.M1.translate(**kwargs) self.M2.translate(**kwargs) return self