예제 #1
0
    def get_intersection(self, segment):
        """
        Calculate the intersection of two line segments
        """

        _lhs = TupleMath.subtract(self.end, self.start)[0:2]
        _lhs = TupleMath.multiply(_lhs, (1.0, -1.0))

        _lhs += (sum(TupleMath.multiply(_lhs, self.start)),)

        _rhs = TupleMath.subtract(segment.end, segment.start)[0:2]
        _rhs = TupleMath.multiply(_lhs, (1.0, -1.0))

        _rhs += (sum(TupleMath.multiply(_rhs, segment.start)),)

        _determinant = TupleMath.cross(_lhs, _rhs, (0, 0, 1))[2]

        if not _determinant:
            return (math.nan, math.nan)

        _intersection = (
            TupleMath.cross(_lhs, _rhs, (1, 0, 0))[0],
            TupleMath.cross(_lhs, _rhs, (0, 1, 0))[1]
        )

        return TupleMath.scale(_intersection, 1.0 / _determinant)
예제 #2
0
def get_ortho_vector(line, distance, side=''):
    """
    Return the orthogonal vector pointing toward the indicated side at the
    provided position.  Defaults to left-hand side
    """

    _dir = 1.0

    _side = side.lower()

    if _side in ['r', 'rt', 'right']:
        _dir = -1.0

    start = tuple(line.get('Start'))
    end = tuple(line.get('End'))
    bearing = line.get('BearingIn')

    if (start is None) or (end is None):
        return None, None

    _delta = TupleMath.subtract(end, start)
    _delta = TupleMath.normalize(_delta)

    _left = tuple(-_delta.y, _delta.x, 0.0)

    _coord = get_coordinate(start, bearing, distance)

    return _coord, TupleMath.multiply(_left, _dir)
예제 #3
0
def get_coordinate(start, bearing, distance):
    """
    Return the x/y coordinate of the line at the specified distance along it
    """

    _vec = TupleMath.bearing_vector(bearing)

    return TupleMath.add(tuple(start),
                         TupleMath.multiply(tuple(_vec), distance))
예제 #4
0
    def validate_coordinates(self, zero_reference):
        """
        Iterate the geometry, testing for incomplete / incorrect station /
        coordinate values. Fix them where possible, error otherwise
        """

        #calculate distance between curve start and end using
        #internal station and coordinate vectors

        _datum = self.data.get('meta')
        _geo_data = self.data.get('geometry')

        _prev_geo = {
            'End': _datum.get('Start'),
            'InternalStation': (0.0, 0.0),
            'StartStation': _datum.get('StartStation'),
            'Length': 0.0
        }

        if zero_reference:
            _prev_geo['End'] = Vector()

        for _geo in _geo_data:

            if not _geo:
                continue

            #get the vector between the two geometries
            #and the station distance
            _vector = TupleMath.subtract(tuple(_geo.get('Start')),
                                         tuple(_prev_geo.get('End')))

            _sta_len = abs(
                _geo.get('InternalStation')[0] \
                    - _prev_geo.get('InternalStation')[1]
            )

            #calculate the difference between the vector length
            #and station distance in document units
            _delta = \
                (TupleMath.length(_vector) - _sta_len) / units.scale_factor()

            #if the stationing / coordinates are out of tolerance,
            #the error is with the coordinate vector or station
            if not support.within_tolerance(_delta):
                bearing_angle = TupleMath.bearing(_vector)

                #fix station if coordinate vector bearings match
                if support.within_tolerance(bearing_angle,
                                            _geo.get('BearingIn')):


                    _int_sta = (
                        _prev_geo.get('InternalStation')[1] \
                            + TupleMath.length(_vector),
                        _geo.get('InternalStation')[0]
                        )

                    _start_sta = _prev_geo.get('StartStation') + \
                                    _prev_geo.get('Length') / \
                                        units.scale_factor() + \
                                           TupleMath.length(_vector) / \
                                               units.scale_factor()

                    _geo['InternalStation'] = _int_sta
                    _geo['StartStation'] = _start_sta

                #otherwise, fix the coordinate
                else:
                    _bearing_vector = TupleMath.multiply(
                        TupleMath.bearing_vector(_geo.get('BearingIn')),
                        _sta_len)

                    _start_pt = TupleMath.add(_prev_geo.get('End'),
                                              _bearing_vector)
                    _geo['Start'] = _start_pt

            _prev_geo = _geo