Ejemplo n.º 1
0
    def test_constrainToRevolution(self):
        """test_revolvePositive doc..."""

        for i in range(100):
            value = random.uniform(-2000.0, 5000.0)
            a = Angle(degrees=value)
            a.constrainToRevolution()
            self.assertLessEqual(a.degrees, 360.0)
            self.assertGreaterEqual(a.degrees, 0.0)
Ejemplo n.º 2
0
    def test_radians(self):
        """test_radians doc..."""
        for i in range(100):
            value = random.uniform(-2000.0, 5000.0)
            a = Angle(radians=value)
            self.assertAlmostEqual(a.radians, value)

        for i in range(100):
            value = random.uniform(-2000.0, 5000.0)
            a = Angle()
            a.radians = value
            self.assertAlmostEqual(a.radians, value)
Ejemplo n.º 3
0
    def test_degrees(self):
        """ doc... """
        for i in range(100):
            value = random.uniform(-2000.0, 5000.0)
            a = Angle(degrees=value)
            self.assertAlmostEqual(a.degrees, value)

        for i in range(100):
            value = random.uniform(-2000.0, 5000.0)
            a = Angle()
            a.degrees = value
            self.assertAlmostEqual(a.degrees, value)
Ejemplo n.º 4
0
    def test_differenceBetween(self):
        """test_differenceBetween doc..."""

        for i in range(1000):
            value = random.uniform(-2000.0, 5000.0)
            a = Angle(degrees=value)
            a.constrainToRevolution()

            value = random.uniform(-2000.0, 5000.0)
            b = Angle(degrees=value)
            b.constrainToRevolution()
            self.assertLessEqual(abs(a.differenceBetween(b).degrees), 180.0)
Ejemplo n.º 5
0
    def _analyzeTrackSeries(self, series, trackway, sitemap):
        if len(series.tracks) < 2:
            return

        prev_track = series.tracks[0]
        for track in series.tracks[1:]:
            stride_line = LineSegment2D(
                start=prev_track.positionValue,
                end=track.positionValue)

            stride_angle = stride_line.angle
            abs_angle = Angle(degrees=prev_track.rotation)


            if not prev_track.left:
                local_angle = stride_angle.differenceBetween(abs_angle)
            else:
                local_angle = abs_angle.differenceBetween(stride_angle)

            has_field_measurements = not prev_track.hasImportFlag(
                ImportFlagsEnum.NO_FIELD_MEASUREMENTS
            )

            if has_field_measurements:
                measuredRotation = prev_track.rotationMeasured
                difference = round(abs(measuredRotation - local_angle.degrees))
                deviation = NumericUtils.roundToOrder(
                    value=difference/prev_track.rotationUncertainty,
                    orderOfMagnitude=-2)
            else:
                measuredRotation = ''
                difference = ''
                deviation = ''

            self._csv.createRow(
                uid=prev_track.uid,
                fingerprint=prev_track.fingerprint,
                difference=difference,
                deviation=deviation,
                localRotation=round(local_angle.degrees),
                measuredRotation=measuredRotation)
            prev_track = track
Ejemplo n.º 6
0
    def angleBetween(self, position):
        """angleBetween doc..."""

        myLength = self.length
        posLength = position.length
        denom = myLength.raw * posLength.raw
        denomUnc = math.sqrt(
            myLength.rawUncertainty * myLength.rawUncertainty +
            posLength.rawUncertainty * posLength.rawUncertainty)

        if denom == 0.0:
            return Angle(radians=0.0, uncertainty=0.5 * math.pi)

        nom = self.x * position.x + self.y * position.y
        nomUnc = (abs(position.x) * self.xUnc + abs(self.x) * position.xUnc +
                  abs(position.y) * self.yUnc +
                  abs(self.y) * position.yUnc) / denom

        b = nom / denom
        bUnc = abs(1.0/denom)*nomUnc + \
            abs(nom/math.pow(denom, 2))*denomUnc

        if NumericUtils.equivalent(b, 1.0):
            return Angle()

        try:
            if NumericUtils.equivalent(b, -1.0):
                a = math.pi
            else:
                a = math.acos(b)
        except Exception:
            print('[ERROR]: Unable to calculate angle between', b)
            return Angle()

        if NumericUtils.equivalent(a, math.pi):
            return Angle(radians=a, uncertainty=180.0)

        try:
            aUnc = abs(1.0 / math.sqrt(1.0 - b * b)) * bUnc
        except Exception:
            print('[ERROR]: Unable to calculate angle between uncertainty', b,
                  a)
            return Angle()

        return Angle(radians=a, uncertainty=aUnc)
Ejemplo n.º 7
0
    def _analyzeTrackSeries(self, series, trackway, sitemap):

        if len(series.tracks) < 2:
            # At least two tracks are required to make the comparison
            return

        for track in series.tracks:
            fieldAngle = Angle(
                degrees=track.rotationMeasured \
                    if track.rotationMeasured \
                    else  0.0)
            dataAngle  = Angle(degrees=track.rotation)
            strideLine = StrideLine(track=track, series=series)

            if track.hidden or strideLine.pairTrack.hidden:
                continue

            try:
                strideLine.vector.normalize()
            except ZeroDivisionError:
                pair = strideLine.pairTrack
                self.logger.write([
                    '[ERROR]: Stride line was a zero length vector',
                    'TRACK: %s (%s, %s) [%s]' % (
                        track.fingerprint,
                        NumericUtils.roundToSigFigs(track.x, 3),
                        NumericUtils.roundToSigFigs(track.z, 3),
                        track.uid),
                    'PAIRING: %s (%s, %s) [%s]' % (
                        pair.fingerprint,
                        NumericUtils.roundToSigFigs(pair.x, 3),
                        NumericUtils.roundToSigFigs(pair.z, 3),
                        pair.uid) ])
                continue

            axisAngle = strideLine.angle
            if track.left:
                fieldAngle.radians += axisAngle.radians
            else:
                fieldAngle.radians = axisAngle.radians - fieldAngle.radians

            # Adjust field angle into range [-180, 180]
            fieldAngle.constrainToRevolution()
            if fieldAngle.degrees > 180.0:
                fieldAngle.degrees -= 360.0

            fieldAngleUnc = Angle(degrees=5.0)
            fieldAngleUnc.radians += \
                0.03/math.sqrt(1.0 - math.pow(strideLine.vector.x, 2))
            fieldDeg = NumericUtils.toValueUncertainty(
                value=fieldAngle.degrees,
                uncertainty=fieldAngleUnc.degrees)

            # Adjust data angle into range [-180, 180]
            dataAngle.constrainToRevolution()
            if dataAngle.degrees > 180.0:
                dataAngle.degrees -= 360.0

            dataAngleUnc = Angle(degrees=track.rotationUncertainty)
            dataDeg = NumericUtils.toValueUncertainty(
                value=dataAngle.degrees,
                uncertainty=dataAngleUnc.degrees)

            angle1 = Angle(degrees=dataDeg.value)
            angle2 = Angle(degrees=fieldDeg.value)

            # fill color for the disks to be added to the map are based on
            # diffDeg
            diffDeg = NumericUtils.toValueUncertainty(
                value=angle1.differenceBetween(angle2).degrees,
                uncertainty=min(90.0, math.sqrt(
                    math.pow(dataAngleUnc.degrees, 2) +
                    math.pow(fieldAngleUnc.degrees, 2))) )

            self._diffs.append(diffDeg.value)

            deviation = diffDeg.value/diffDeg.uncertainty
            self.deviations[track.uid] = diffDeg

            # for now, convert +/- 180 headings to 0-360, using e and m
            # comment the next four lines toggle comments for entered and
            # measured below to revert
            e = dataDeg.value
            m = fieldDeg.value
            if e < 0.0:
                e += 360.0
            if m < 0.0:
                m += 360.0

            data = dict(
                uid=track.uid,
                fingerprint=track.fingerprint,
                entered=str(e),
                measured=str(m),
                delta=abs(diffDeg.value),
                deviation=deviation,
                relative=NumericUtils.roundToOrder(track.rotationMeasured, -2),
                axis=NumericUtils.roundToOrder(axisAngle.degrees, -2),
                axisPairing='NEXT' if strideLine.isNext else 'PREV')
            self._csv.createRow(**data)

            data['track'] = track
            self._data.append(data)

            # draw the stride line pointer for reference in green
            self._currentDrawing.use(
                'pointer',
                (track.x, track.z),
                scene=True,
                rotation=axisAngle.degrees,
                stroke_width=1,
                scale=0.5,
                stroke='green')

            # indicate in blue the map-derived estimate of track rotation
            self._currentDrawing.use(
                'pointer',
                (track.x, track.z),
                scene=True,
                rotation=dataDeg.value,
                stroke_width=1,
                stroke='blue')

            # add the measured (spreadsheet) estimate of rotation
            self._currentDrawing.use(
                'pointer',
                (track.x, track.z),
                scene=True,
                rotation=fieldDeg.value,
                stroke_width=1,
                stroke='red')

            # place a translucent disk of radius proportional to the difference
            # in degrees
            radius = 100.0*diffDeg.value/180.0
            self._currentDrawing.circle(
                (track.x, track.z),
                radius,
                scene=True,
                fill='red',
                stroke_width=0.5,
                stroke='red',
                fill_opacity='0.5')
Ejemplo n.º 8
0
    def closestPointOnLine(self, point, contained =True):
        """ Finds the closest point on a line to the specified point using the formulae
            discussed in the "another formula" section of:
            http://en.m.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Another_formula """

        length = self.length
        if not length:
            raise ValueError('Cannot calculate point. Invalid line segment.')

        s = self.start
        e = self.end
        deltaX = e.x - s.x
        deltaY = e.y - s.y
        rotate = False
        slope = 0.0
        slopeUnc = 0.0

        try:
            slope = deltaY/deltaX
            slopeUnc = abs(1.0/deltaX)*(s.yUnc + e.yUnc) + abs(slope/deltaX)*(s.xUnc + e.xUnc)
        except Exception:
            rotate = True

        if rotate or (abs(slope) > 1.0 and abs(slopeUnc/slope) > 0.5):
            a = Angle(degrees=20.0)
            line = self.clone()
            line.rotate(a, self.start)
            p = point.clone()
            p.rotate(a, self.start)
            result = line.closestPointOnLine(p, contained=contained)
            if result is None:
                return result

            a.degrees = -20.0
            result.rotate(a, self.start)
            return result

        intercept = s.y - slope*s.x
        denom = slope*slope + 1.0
        numer = point.x + slope*(point.y - intercept)

        x = numer/denom
        y = (slope*numer)/denom + intercept

        if contained:
            # Check to see if point is between start and end values
            xRange = sorted([self.start.x, self.end.x])
            yRange = sorted([self.start.y, self.end.y])
            eps = 1e-8
            xMin = x - eps
            xMax = x + eps
            yMin = y - eps
            yMax = y + eps
            if xRange[1] < xMin or xMax < xRange[0] or yRange[1] < yMin or yMax < yRange[0]:
                return None

        pos = PositionValue2D(x=x, y=y)

        startDist = self.start.distanceTo(pos)
        endDist = self.end.distanceTo(pos)

        xUnc = startDist.raw/length.raw*self.start.xUnc + endDist.raw/length.raw*self.end.xUnc
        pos.xUnc = math.sqrt(xUnc**2 + point.xUnc**2)

        yUnc = startDist.raw/length.raw*self.start.yUnc + endDist.raw/length.raw*self.end.yUnc
        pos.yUnc = math.sqrt(yUnc**2 + point.yUnc**2)

        return pos