Пример #1
0
class Color(StrongPropertyInitializer):
    """Defines a color in terms of a name and RGB values"""
    name = StringProperty()
    red = NumberProperty(default=0.0, restriction=RESTRICT_FRACTION)
    green = NumberProperty(default=0.0, restriction=RESTRICT_FRACTION)
    blue = NumberProperty(default=0.0, restriction=RESTRICT_FRACTION)

    def __init__(self, red=0.0, green=0.0, blue=0.0, **kwargs):
        super(Color, self).__init__(red=red, green=green, blue=blue, **kwargs)

    def rgb_tuple(self):
        return (self.red, self.green, self.blue)

    def numpy_array(self):
        import numpy
        return numpy.array([self.red, self.green, self.blue])

    def set(self, red, green, blue):
        self.red = red
        self.green = green
        self.blue = blue

    def html_string(self):
        return "#%02X%02X%02X" % (self.red * 255, self.green * 255,
                                  self.blue * 255)

    def __eq__(self, other):
        return other.red == self.red and other.green == self.green and other.blue == self.blue

    def __neq__(self, other):
        return other.red != self.red or other.green != self.green or other.blue != self.blue

    def __str__(self):
        return self.name
Пример #2
0
class ShapeGrow(__ShapeModifier__):
    """ generates a shape with uniformly grows """
    offset = DefinitionProperty(fdef_name="define_offset")
    amount = NumberProperty(required=True)

    def __init__(self, original_shape, amount, **kwargs):
        super(ShapeGrow, self).__init__(original_shape=original_shape,
                                        amount=amount,
                                        **kwargs)

    def is_closed(self):
        return self.original_shape.is_closed()

    closed = FunctionProperty(is_closed, Shape.set_closed)

    def define_offset(self):
        o = self.original_shape.orientation() * self.amount
        return o

    def define_points(self, pts):
        original = Shape(self.original_shape).remove_straight_angles()
        if len(original) <= 1: return

        a2 = original.angles_rad() * 0.5
        a1 = roll(a2, 1)

        a_plus = a2 + a1

        cos_a_min = cos(a2 - a1)
        offsets = column_stack((-sin(a_plus) / cos_a_min,
                                cos(a_plus) / cos_a_min)) * (self.offset)

        # compute offsets from each point
        pts = (original.points + offsets)
        return pts
Пример #3
0
class ShapeOffset(__ShapeStartEndAngle__):
    """ generates a shape with a given offset from its original shape"""
    offset = NumberProperty(required=True)

    def __init__(self, original_shape, offset, **kwargs):
        super(ShapeOffset, self).__init__(original_shape=original_shape,
                                          offset=offset,
                                          **kwargs)

    def define_points(self, pts):
        original = self.__get_original_shape_without_straight_angles__()
        if len(original) <= 1: return

        a2 = original.angles_rad() * 0.5
        a1 = roll(a2, 1)

        if original.closed:
            a2[-1] = a2[0]
            a1[0] = a1[-1]
        else:
            a2[-1] = self.end_face_angle * DEG2RAD - a2[-2]
            a1[0] = self.start_face_angle * DEG2RAD - a1[1]

        a_plus = a2 + a1
        cos_a_min = cos(a2 - a1)
        offsets = column_stack((-sin(a_plus) / cos_a_min,
                                cos(a_plus) / cos_a_min)) * (self.offset)

        # compute offsets from each point
        pts = (original.points + offsets)
        return pts
Пример #4
0
class __ARef1dElement__(ARef):
    period = DefinitionProperty(fdef_name="define_period")
    n_o_periods = DefinitionProperty(fdef_name="define_n_o_periods")

    period_1d = NumberProperty(default=1.0, restriction=RESTRICT_NONZERO)
    n_o_periods_1d = IntProperty(default=1, restriction=RESTRICT_POSITIVE)

    def __init__(self,
                 reference,
                 origin,
                 period_1d,
                 n_o_periods_1d,
                 transformation=None,
                 **kwargs):
        kwargs["period"] = SUPPRESSED
        kwargs["n_o_periods"] = SUPPRESSED
        super(__ARef1dElement__, self).__init__(reference=reference,
                                                origin=origin,
                                                period_1d=period_1d,
                                                n_o_periods_1d=n_o_periods_1d,
                                                transformation=transformation,
                                                **kwargs)

    def is_empty(self):
        return __RefElement__.is_empty(self) or (self.n_o_periods_1d == 0)
Пример #5
0
    class CircuitModel(twoshape.CoreCladdingShapeWaveguide.CircuitModel):
        phase_error = NumberProperty()

        def _default_phase_error(self):
            if not hasattr(self.template, 'phase_error_sigma'):
                import warnings
                warnings.warn(
                    'Trace template has no phase_error_sigma variable, setting it to 0'
                )
                return 0

            phase_error_sigma = self.template.phase_error_sigma

            if phase_error_sigma == 0.0:
                return 0.0

            return np.random.normal(0.0, phase_error_sigma)

        def _generate_model(self):
            from aeponyx.compactmodels import WGPhaseErrorCompactModel
            model = WGPhaseErrorCompactModel(
                n_g=self.template.n_g,
                n_eff=self.template.n_eff,
                center_wavelength=self.template.center_wavelength,
                length=self.length,
                phase_error=self.phase_error)
            return model
Пример #6
0
class NoDistortTransform(GenericNoDistortTransform):
    """ A homothetic transformation that does not distort the item it is applied to (angle conservation) 
        The transform is defined by 
        - a mirror around the x-axis
        - a scaling with respect to the origin
        - a rotation around the origin
        - a translation
        
        it is also possible to set absolute magnification and rotation, which means that subsequent transformations
        will not affect the angle and size any further
        """
    # FIXME : Use transformation matrix which is computed once (and cached)
    
    def __init__(self, translation = (0.0, 0.0), rotation = 0.0, magnification = 1.0, v_mirror = False, absolute_magnification = False, absolute_rotation = False, **kwargs):
        # note: translation is no part of gdsII transform. It should be taken into account while writing the file
        super(NoDistortTransform, self).__init__(
            translation = translation,
            rotation = rotation,
            magnification = magnification,
            v_mirror = v_mirror,
            absolute_magnification = absolute_magnification,
            absolute_rotation =absolute_rotation,
            **kwargs)

    translation = Coord2Property("__translation__", default = (0.0, 0.0))
    """ the translation coordinate """
    
   
    #def get_rotation (self): return self.rotation
    def set_rotation(self, value):
        self.__rotation__ = value % 360.0
        if value % 90.0 == 0.0:
            # make sure sine and cosine are really zero when needed!
            if self.__rotation__ == 0.0:
                self.__ca__ = 1.0
                self.__sa__ = 0.0
            elif self.__rotation__ == 90.0:
                self.__ca__ = 0.0
                self.__sa__ = 1.0
            elif self.__rotation__ == 180.0:
                self.__ca__ = -1.0
                self.__sa__ = 0.0
            elif self.__rotation__ == 270.0:
                self.__ca__ = 0.0
                self.__sa__ = -1.0
        else:
            self.__ca__ = cos(value * DEG2RAD)
            self.__sa__ = sin(value * DEG2RAD)
    rotation = SetFunctionProperty("__rotation__", set_rotation, default=0.0)
    """ the rotation around the origin """

    magnification = NumberProperty("__magnification__", restriction = RESTRICT_NONZERO, default = 1.0)
    """ the magnification factor """

    v_mirror = BoolProperty("__v_mirror__", default = False)
    """ the vertical mirror """
    flip = v_mirror
    

    #""" set absolute magnification on or off"""
    absolute_magnification = BoolProperty("__absolute_magnification__", default = False)
    
    #""" set absolute rotation on or off"""
    absolute_rotation = BoolProperty("__absolute_rotation__", default = False)
    
    def __make_simple__(self):
        """ internal use: reduces special subclasses to this generic type """
        # if you change special types, they should revert to generic type
        self.__class__ = NoDistortTransform

    def __translate__(self, coord):
        """ internal use: applies translation to a coordinate """
        return Coord2(coord[0] + self.translation.x, coord[1] + self.translation.y)
    
    def __rotate__(self, coord):
        """ internal use: applies rotation to a coordinate """
        return Coord2(coord[0] * self.__ca__ - coord[1] * self.__sa__, coord[0] * self.__sa__ + coord[1] * self.__ca__)

    def __magnify__(self, coord):
        """ internal use: applies magnification to a coordinate """
        return Coord2(coord[0] * self.magnification, coord[1] * self.magnification)

    def __v_flip__(self, coord):
        """ internal use: applies v_mirror to a coordinate """
        if self.v_mirror:
            return Coord2(coord[0], -coord[1])
        else:
            return Coord2(coord[0], coord[1])

    def __inv_translate__(self, coord):
        """ internal use: applies reverse translation to a coordinate """
        return Coord2(coord[0] - self.translation.x, coord[1] - self.translation.y)
    
    def __inv_rotate__(self, coord):
        """ internal use: applies reverse rotation to a coordinate """
        return Coord2(coord[0] * self.__ca__ + coord[1] * self.__sa__, - coord[0] * self.__sa__ + coord[1] * self.__ca__)

    def __inv_magnify__(self, coord):
        """ internal use: applies reverse magnification to a coordinate """
        return Coord2(coord[0] / self.magnification, coord[1] / self.magnification)

    def __inv_v_flip__(self, coord):
        """ internal use: applies reverse v_mirror to a coordinate """
        if self.v_mirror:
            return Coord2(coord[0], - coord[1])
        else:
            return Coord2(coord[0], coord[1])

    def __translate3__(self, coord):
        """ internal use: applies translation to a 3d coordinate """
        return Coord3(coord[0] + self.translation.x, coord[1] + self.translation.y, coord[2])
    
    def __rotate3__(self, coord):
        """ internal use: applies rotation to a 3d coordinate """
        return Coord3(coord[0] * self.__ca__ - coord[1] * self.__sa__, coord[0] * self.__sa__ + coord[1] * self.__ca__, coord[2])

    def __magnify3__(self, coord):
        """ internal use: applies magnification to a 3d coordinate """
        return Coord3(coord[0] * self.magnification, coord[1] * self.magnification, coord[2])

    def __v_flip3__(self, coord):
        """ internal use: applies v_mirror to a 3d coordinate """
        if self.v_mirror:
            return Coord3(coord[0], -coord[1], coord[2])
        else:
            return Coord3(coord[0], coord[1], coord[2])

    def __inv_translate3__(self, coord):
        """ internal use: applies reverse translation to a 3d coordinate """
        return Coord3(coord[0] - self.translation.x, coord[1] - self.translation.y, coord[2])
    
    def __inv_rotate3__(self, coord):
        """ internal use: applies reverse rotation to a 3d coordinate """
        return Coord3(coord[0] * self.__ca__ + coord[1] * self.__sa__, - coord[0] * self.__sa__ + coord[1] * self.__ca__, coord[2])

    def __inv_magnify3__(self, coord):
        """ internal use: applies reverse magnification to a 3d coordinate """
        return Coord3(coord[0] / self.magnification, coord[1] / self.magnification, coord[2])

    def __inv_v_flip3__(self, coord):
        """ internal use: applies reverse v_mirror to a 3d coordinate """
        if self.v_mirror:
            return Coord3(coord[0], - coord[1], coord[2])
        else:
            return Coord3(coord[0], coord[1], coord[2])
        
    def __translate_array__(self, coords):
        """ internal use: applies translation to a numpy array """
        coords += numpy.array([self.translation.x, self.translation.y])
        return coords
    
    def __rotate_array__(self, coords):
        """ internal use: applies rotation to a numpy array """
        x_a = numpy.array([self.__ca__, -self.__sa__])
        y_a = numpy.array([self.__sa__, self.__ca__])
        coords = numpy.transpose(numpy.vstack((numpy.sum(coords * x_a, 1), numpy.sum(coords * y_a, 1))))
        return coords

    def __magnify_array__(self, coords):
        """ internal use: applies magnification to a numpy array """
        coords *= numpy.array([self.magnification, self.magnification])
        return coords

    def __v_flip_array__(self, coords):
        """ internal use: applies v_mirror to a numpy array """
        coords *= (numpy.array([False, self.v_mirror]) * -2.0 + 1.0)
        return coords

    def __inv_translate_array__(self, coords):
        """ internal use: applies reverse translation to a numpy array """
        coords -= numpy.array([self.translation.x, self.translation.y])
        return coords
    
    def __inv_rotate_array__(self, coords):
        """ internal use: applies reverse rotation to a numpy array """
        x_a = array([self.__ca__, self.__sa__])
        y_a = array([-self.__sa__, self.__ca__])
        coords = numpy.transpose(numpy.vstack((numpy.sum(coords * x_a, 1), numpy.sum(coords * y_a, 1))))
        return coords

    def __inv_magnify_array__(self, coords):
        """ internal use: applies reverse magnification to a numpy array """
        coords *= numpy.array([1.0 / self.magnification, 1.0 / self.magnification])
        return coords

    def __inv_v_flip_array__(self, coords):
        """ internal use: applies reverse v_mirror to a numpy array """
        coords *= numpy.array([False, self.v_mirror]) * (-2.0) + 1.0
        return coords

    def __translate_array3__(self, coords):
        """ internal use: applies translation to a numpy array """
        coords += numpy.array([self.translation.x, self.translation.y, 0.0])
        return coords
    
    def __rotate_array3__(self, coords):
        """ internal use: applies rotation to a numpy array """
        x_a = numpy.array([self.__ca__, -self.__sa__, 0])
        y_a = numpy.array([self.__sa__, self.__ca__, 0])
        z_a = numpy.array([0, 0, 1.0])
        
        coords = numpy.transpose(numpy.vstack((numpy.sum(coords * x_a, 1), numpy.sum(coords * y_a, 1), numpy.sum(coords * z_a, 1))))
        return coords

    def __magnify_array3__(self, coords):
        """ internal use: applies magnification to a numpy array """
        coords *= numpy.array([self.magnification, self.magnification, 1.0])
        return coords

    def __v_flip_array3__(self, coords):
        """ internal use: applies v_mirror to a numpy array """
        coords *= (numpy.array([False, self.v_mirror, False]) * -2.0 + 1.0)
        return coords

    def __inv_translate_array3__(self, coords):
        """ internal use: applies reverse translation to a numpy array """
        coords -= numpy.array([self.translation.x, self.translation.y, 0.0])
        return coords
    
    def __inv_rotate_array3__(self, coords):
        """ internal use: applies reverse rotation to a numpy array """
        x_a = array([self.__ca__, self.__sa__, 0.0])
        y_a = array([-self.__sa__, self.__ca__, 0.0])
        z_a = numpy.array([0, 0, 1.0])
        
        coords = numpy.transpose(numpy.vstack((numpy.sum(coords * x_a, 1), numpy.sum(coords * y_a, 1), numpy.sum(coords * z_a, 1))))
        return coords

    def __inv_magnify_array3__(self, coords):
        """ internal use: applies reverse magnification to a numpy array """
        coords *= numpy.array([1.0 / self.magnification, 1.0 / self.magnification, 1.0])
        return coords

    def __inv_v_flip_array3__(self, coords):
        """ internal use: applies reverse v_mirror to a numpy array """
        coords *= numpy.array([False, self.v_mirror, False]) * (-2.0) + 1.0
        return coords

    def apply_to_coord(self, coord):
        """ applies transformation to a coordinate """
        # this could be speeded up
        # Check the east order
        coord = self.__v_flip__(coord)# first flip 
        coord = self.__rotate__(coord)# then magnify
        coord = self.__magnify__(coord)# then rotate
        coord = self.__translate__(coord) # finally translate
        return coord
    
    def reverse_on_coord(self, coord):
        """ applies reverse transformation to a coordinate """
        # this could be speeded up
        # Check the right order
        coord = self.__inv_translate__(coord) # finally translate
        coord = self.__inv_magnify__(coord)# then rotate
        coord = self.__inv_rotate__(coord)# then magtnify
        coord = self.__inv_v_flip__(coord)# first flip 
        return coord

    def apply_to_array(self, coords):
        """ internal use: applies transformation to a numpy array"""
        # this could be speeded up
        # Check the right order
        coords = self.__v_flip_array__(coords)# first flip 
        coords = self.__rotate_array__(coords)# then rotate
        coords = self.__magnify_array__(coords)# then magnify
        coords = self.__translate_array__(coords) # finally translate
        return coords
    
    def reverse_on_array(self, coord):
        """ internal use: applies reverse transformation to a numpy array """
        # this could be speeded up
        # Check the right order
        coords = self.__inv_translate_array__(coords) # finally translate
        coords = self.__inv_magnify_array__(coords)# then magnify
        coords = self.__inv_rotate_array__(coords)# then rotate
        coords = self.__inv_v_flip_array__(coords)# first flip 
        return coords    

    def apply_to_coord3(self, coord):
        """ applies transformation to a coordinate """
        # this could be speeded up
        # Check the east order
        coord = self.__v_flip3__(coord)# first flip 
        coord = self.__rotate3__(coord)# then magnify
        coord = self.__magnify3__(coord)# then rotate
        coord = self.__translate3__(coord) # finally translate
        return coord
    
    def reverse_on_coord3(self, coord):
        """ applies reverse transformation to a coordinate """
        # this could be speeded up
        # Check the right order
        coord = self.__inv_translate3__(coord) # finally translate
        coord = self.__inv_magnify3__(coord)# then rotate
        coord = self.__inv_rotate3__(coord)# then magtnify
        coord = self.__inv_v_flip3__(coord)# first flip 
        return coord

    def apply_to_array3(self, coords):
        """ internal use: applies transformation to a numpy array"""
        # this could be speeded up
        # Check the right order
        coords = self.__v_flip_array3__(coords)# first flip 
        coords = self.__rotate_array3__(coords)# then rotate
        coords = self.__magnify_array3__(coords)# then magnify
        coords = self.__translate_array3__(coords) # finally translate
        return coords
    
    def reverse_on_array3(self, coord):
        """ internal use: applies reverse transformation to a numpy array """
        # this could be speeded up
        # Check the right order
        coords = self.__inv_translate_array3__(coords) # finally translate
        coords = self.__inv_magnify_array3__(coords)# then magnify
        coords = self.__inv_rotate_array3__(coords)# then rotate
        coords = self.__inv_v_flip_array3__(coords)# first flip 
        return coords    
    
    
    def apply_to_angle_deg(self, angle):
        """ applies transformation to an absolute angle (degrees) """
        a = angle
        if self.v_mirror:
            a = -a
        a += self.rotation
        return a % 360.0
    
    def reverse_on_angle_deg(self, angle):
        """ applies reverse transformation to an absolute angle (degrees)"""
        a = angle - self.rotation
        if self.v_mirror:
            a = -a
        return a % 360.0

    def apply_to_angle_rad(self, angle):
        """ applies transformation to an absolute angle (radians) """
        a = angle
        if self.v_mirror:
            a = -a
        a += self.rotation * DEG2RAD
        return a % (2 * pi)
    
    def reverse_on_angle_rad(self, angle):
        """ applies reverse transformation to an absolute angle (radians) """
        a = angle - self.rotation * DE2RAD
        if self.v_mirror:
            a = -a
        return a % (2 * pi)

    def apply_to_length(self, length):
        """ applies transformation to a distance """
        return length * self.magnification

    def reverse_on_length(self, length):
        """ applies reverse transformation to a distance """
        return length / self.magnification

    def __neg__(self):
        """ returns the reverse transformation """
        from .translation import Translation
        from .rotation import Rotation
        from .magnification import Magnification
        from .mirror import VMirror
        
        T = Translation(- self.translation) + Magnification((0.0, 0.0), 1 / self.magnification) + Rotation((0.0, 0.0), -self.rotation)
        if self.v_mirror:
            T += VMirror(0.0)
        return T

    def __sub__(self, other):
        """ returns the concatenation of this transform and the reverse of other """
        if other is None: return copy.deepcopy(self)
        if not isinstance(other, __ReversibleTransform__):
            raise TypeError("Cannot subtract an irreversible transform")
        return self.__add__(-other)

    def __isub__(self, other):
        """ concatenates the reverse of other to this transform """
        if other is None: return self
        if not isinstance(other, __ReversibleTransform__):
            raise TypeError("Cannot subtract an irreversible transform")
        return self.__iadd__(self, -other)

    def __add__(self, other):
        """ returns the concatenation of this transform and other """
        # performs transformation "other" after "self" and returns resulting transform
        if other is None: return copy.deepcopy(self)

        if isinstance(other, NoDistortTransform):
            T = NoDistortTransform()

            if self.absolute_magnification:
                M1 = 1.0
            else:
                M1 = other.magnification
            T.magnification = self.magnification * M1

            #flip signs
            if other.v_mirror: s_1 = -1
            else:              s_1 = 1

            if not self.absolute_rotation:
                T.rotation = s_1 * self.rotation + other.rotation
                ca = other.__ca__
                sa = other.__sa__
            else:
                T.rotation = s_1 * self.rotation
                ca = 1.0
                sa = 0.0


            # tricky part: translation
            T.translation = Coord2(other.translation.x + ca * self.translation.x * M1 - s_1 * sa * self.translation.y * M1,
                                   other.translation.y + sa * self.translation.x * M1 + s_1 * ca * self.translation.y * M1)

            T.absolute_rotation = self.absolute_rotation or other.absolute_rotation
            T.absolute_magnification = self.absolute_magnification or other.absolute_magnification
            T.v_mirror = (not self.v_mirror == other.v_mirror)
        else:
            T = Transform.__add__(self, other)
        return T

    def __iadd__(self, other):
        """ concatenates other to this transform """
        if other is None: return self
        # performs transformation other after self and returns self
        if isinstance(other, NoDistortTransform):
            # tricky part: translation
            if self.absolute_magnification:
                self.magnification = self.magnification * other.magnification
                M1 = 1
            else:
                M1 = other.magnification

            #flip signs
            if other.v_mirror: s_1 = -1
            else:              s_1 = 1


            if not self.absolute_rotation:
                self.rotation = s_1 * self.rotation + other.rotation
                ca = other.__ca__
                sa = other.__sa__
            else:
                self.rotation = s_1 * self.rotation                
                ca = 1
                sa = 0

            # tricky part: translation
            self.translation = (other.translation.x + ca * self.translation.x * M1 - s_1 * sa * self.translation.y * M1,
                                other.translation.y + sa * self.translation.x * M1 + s_1 * ca * self.translation.y * M1)

            self.absolute_rotation = self.absolute_rotation or other.absolute_rotation
            self.absolute_magnification = self.absolute_magnification or other.absolute_magnification
            self.v_mirror = (not self.v_mirror == other.v_mirror)
        else:
            raise TypeError("Error: Cannot perform += operation for NoDistortTransform and other transform of type " + str(type(other)))
        return self
    
    def __eq__(self, other):
        """ check if the transforms do the same thing """
        if other is None: return self.is_identity()
        if not isinstance(other, NoDistortTransform): return False
        return ((self.rotation == other.rotation) and
                (self.translation == other.translation) and
                (self.v_mirror == other.v_mirror) and
                (self.magnification == other.magnification) and
                (self.absolute_rotation == other.absolute_rotation) and
                (self.absolute_magnification == other.absolute_magnification)
                )

    def __ne__(self, other):
        """ checks if the transforms do different things """

        if other is None: return not self.is_identity()
        if not isinstance(other, NoDistortTransform): return False
        return ((self.rotation != other.rotation) or
                (self.translation != other.translation) or
                (self.v_mirror != other.v_mirror) or
                (self.magnification != other.magnification) or
                (self.absolute_rotation != other.absolute_rotation) or 
                (self.absolute_magnification != other.absolute_magnification)
                )
        
    def is_identity(self):
        """ returns True if the transformation does nothing """
        return ((self.rotation == 0.0) and
                (self.translation.x == 0.0) and
                (self.translation.y == 0.0) and
                not (self.v_mirror) and 
                (self.magnification == 1.0)
            )

    def is_isometric(self):
        """ returns True if the transformation conserves angles and distances """
        return self.magnification == 1.0

    def is_homothetic(self):
        """ returns True if the transformation conserves angles """
        return True

    def is_orthogonal(self):
        """ returns True if the transformation does only rotate on 90degree angles """
        return (self.rotation % 90.0) == 0.0

    def is_octogonal(self):
        """ returns True if the transformation does only rotate on 45degree angles """
        return (self.rotation % 45.0) == 0.0
    
    def id_string(self):
        """ gives a hash of the transform (for naming purposes) """
        return str(hash("R" + str(int(self.rotation * 10000)) + 
                        "T" + str(int(self.translation[0] * 1000)) + "_" + str(int(self.translation[1] * 1000)) +
                        "M" + str(int(self.magnification * 1000)) +
                        "V" + str(self.v_mirror) +
                        "AM" + str(self.absolute_magnification) +
                        "AR" + str(self.absolute_rotation) 
                        ))
    
    def __str__(self):
        """ gives a string representing the transform """
        return "R=%s-T=%s-M=%s-V=%s-AM=%s-AR=%s" % (str(int(self.rotation * 10000)), 
                                        str(int(self.translation[0] * 1000)) + "_" + str(int(self.translation[1] * 1000)),
                                        str(int(self.magnification * 1000)),
                                        str(self.v_mirror),
                                        str(self.absolute_magnification),
                                        str(self.absolute_rotation))    
Пример #7
0
class StraightLine(transformable.Transformable, StrongPropertyInitializer):
    """ creates a line ax + by + c = 0 """
    a = NumberProperty(required=True)
    b = NumberProperty(required=True)
    c = NumberProperty(required=True)

    def __init__(self, a, b, c, **kwargs):
        super(StraightLine, self).__init__(a=a, b=b, c=c, **kwargs)

    def get_slope(self):
        if self.b == 0:
            return None
        return -self.a / self.b

    slope = property(get_slope, doc="gives slope (tangent) of the line" "")

    def is_on_line(self, coordinate):
        """ returns True if point is on line """
        return abs(self.a * coordinate[0] + self.b * coordinate[1] +
                   self.c) < 1E-10

    def get_angle_rad(self):
        return atan2(-self.a, self.b)

    angle_rad = property(get_angle_rad, doc="gives angle of line (in radians)")

    def get_angle_deg(self):
        return RAD2DEG * self.angle_rad

    angle_deg = property(get_angle_deg, doc="gives angle of line (in radians)")

    def get_y_intercept(self):
        if self.b == 0.0:
            return None
        return -self.c / -self.b

    y_intercept = property(
        get_y_intercept,
        doc="gives y-intercept of line (None if parallel to Y)")

    def get_x_intercept(self):
        if self.a == 0.0:
            return None
        return -self.c / -self.a

    x_intercept = property(
        get_x_intercept,
        doc="gives x-intercept of line (None if parallel to X)")

    def distance(self, coordinate):
        """ gives distance of point to line """
        return abs(self.a * coordinate[0] + self.b * coordinate[1] + self.c
                   ) / sqrt(self.a**2 + self.b**2)

    def intersection(self, line):
        """ gives intersection of line with other line """
        if (self.b * line.a - self.a * line.b) == 0.0:
            return None
        return Coord2(-(self.b * line.c - line.b * self.c) /
                      (self.b * line.a - self.a * line.b),
                      (self.a * line.c - line.a * self.c) /
                      (self.b * line.a - self.a * line.b))

    def closest_point(self, point):
        """ gives closest point on line """
        line2 = straight_line_from_point_angle(point, self.angle_deg + 90.0)
        return self.intersection(line2)

    def is_on_same_side(self, point1, point2):
        """ returns True is both points are on the same side of the line """
        return numpy.sign(self.a * point1[0] +
                          self.b * point1[1] + self.c) == numpy.sign(
                              self.a * point2[0] + self.b * point2[1] + self.c)

    def is_parallel(self, other):
        """ returns True is lines are parallel """
        return abs(self.a * other.b - self.b * other.a) < 1E-10

    def __eq__(self, other):
        return abs(self.a * other.b - self.b * other.a) < 1E-10 and abs(
            self.c * other.b - self.b * other.c) < 1E-10 and abs(
                self.a * other.c - self.c * other.a) < 1E-10

    def __ne__(self, other):
        return (not self.__eq__(other))

    def __get_2_points__(self):
        """ returns 2 points on the line. If a horizontal or vertical, it returns one point on the axis, and another 1.0 further.
            If the line is oblique, it returns the intersects with the axes """
        from .shape import Shape
        if b == 0:
            return Shape(
                [Coord2(-self.c / self.a, 0.0),
                 Coord2(-self.c / self.a, 1.0)])
        elif a == 0:
            return Shape(
                [Coord2(0.0, -self.c / self.b),
                 Coord2(1.0, -self.c / self.b)])
        else:
            return Shape(
                [Coord2(-self.c / self.a, 0.0),
                 Coord2(0.0, -self.c / self.b)])

    def transform(self, transformation):
        """ transforms the straight line with a given transformation """
        p = self.__get_2_points__().transform(transformation)
        self.a = y2 - y1
        self.b = x1 - x2
        self.c = (x2 - x1) * y1 - (y2 - y1) * x1

    def transform_copy(self, transformation):
        """ transforms a copy of the straight line with a given transformation """
        p = self.__get_2_points__().transform(transformation)
        return straight_line_from_two_points(p[0], p[1])