equalize method

GeoPath<GeoLatLng> equalize(
  1. num distanceInMeterPerTime, {
  2. bool smoothPath = true,
})

Splits the path into even sections.

The section size is defined with distanceInMeterPerTime. distanceInMeterPerTime means that the original size on the given path will stay the same but the created section could be smaller because of the "linear distance"

However - if you follow the steps in a given time then the distance from point to point (over time) is correct. (Almost - because of the curves generate with CatmullRomSpline2D

final Path path = new Path.from(zigzag);

If smoothPath is turned on than the minimum of 3 coordinates is required otherwise we need two

Implementation

GeoPath equalize(final num distanceInMeterPerTime,{ final bool smoothPath: true }) {
    GValidate.isTrue(distanceInMeterPerTime > 0, "Distance must be greater than 0");
    GValidate.isTrue((smoothPath && _coordinates.length >= 3) ||
        (!smoothPath&& _coordinates.length >= 2),
            "At least ${smoothPath ? 3 : 2} coordinates are needed to create the steps in between");


    // If we "smooth" the path every second step becomes a spline - so every other step
    // becomes a "Keyframe". A step on the given path
    final double stepDistance = smoothPath ? distanceInMeterPerTime * 2.0 : distanceInMeterPerTime.toDouble();

    final double baseLength = distance.toDouble();
    GValidate.isTrue(baseLength >= stepDistance,
        "Path distance must be at least ${stepDistance}mn (step distance) but was ${baseLength}");

    if(stepDistance > baseLength / 2) {
        _logger.warning("Equalizing the path (L: $baseLength) with a key-frame distance of $stepDistance leads to"
            "weired results. Turn of path smooting.");
    }

    // no steps possible - so return an empty path
    if(baseLength == stepDistance) {
        return new GeoPath.from([ _coordinates.first, _coordinates.last ]);
    }

    final List<T> tempCoordinates = new List.from(_coordinates);
    final GeoPath path = new GeoPath();

    double remainingSteps = 0.0;
    double bearing;

    path.add(tempCoordinates.first);
    T baseStep = tempCoordinates.first;

    for(int index = 0;index < coordinates.length - 1;index++) {
        final double distance = _distance(tempCoordinates[index],tempCoordinates[index + 1]).toDouble();

        // Remember the direction
        bearing = _distance.bearing(tempCoordinates[index],tempCoordinates[index + 1]);

        if(remainingSteps <= distance || (stepDistance - remainingSteps) <= distance) {

            // First step position
            double firstStepPos = stepDistance - remainingSteps;

            final double steps = ((distance - firstStepPos) / stepDistance) + 1;

            final int fullSteps = steps.toInt();
            remainingSteps = round(fullSteps > 0 ? steps % fullSteps : steps,decimals: 6) * stepDistance;

            baseStep = tempCoordinates[index];

            for(int stepCounter = 0; stepCounter < fullSteps;stepCounter++) {
                // Add step on the given path
                // Intermediate step is necessary to stay type-safe
                final GeoLatLng tempStep = _distance.offset(baseStep,firstStepPos,bearing);
                final GeoLatLng nextStep = _latLngFactory(tempStep.latitude,tempStep.longitude);
                path.add(nextStep);
                firstStepPos += stepDistance;

                if(smoothPath) {
                    // Now - split it
                    CatmullRomSpline2D<double> spline;

                    if(path.nrOfCoordinates == 3) {
                        spline = _createSpline(path[0],path[0],path[1],path[2]);

                        // Insert new point between 0 and 1
                        path.coordinates.insert(1,_pointToLatLng(spline.percentage(50)));

                    } else if(path.nrOfCoordinates > 3) {
                        final int baseIndex = path.nrOfCoordinates - 1;
                        spline = _createSpline(
                            path[baseIndex - 3], path[baseIndex - 2], path[baseIndex - 1], path[baseIndex]);

                        // Insert new point at last position - 2 (pushes the next 2 items down)
                        path.coordinates.insert(baseIndex - 1,_pointToLatLng(spline.percentage(50)));
                    }
                }
            }

        } else {
            remainingSteps += distance;
        }
    }

    // If last step is on the same position as the last generated step
    // then don't add the last base step.
    if(baseStep.round() != tempCoordinates.last.round() &&
        baseStep.round() != tempCoordinates.first.round() &&
        round(_distance(baseStep,tempCoordinates.last).toDouble()) > 1) {
        path.add(tempCoordinates.last);
    }

    if(smoothPath) {

        // Last Spline between the last 4 elements
        int baseIndex = path.nrOfCoordinates - 1;
        if(baseIndex > 3) {
            final CatmullRomSpline2D<double> spline = _createSpline(
                path[baseIndex - 3], path[baseIndex - 2], path[baseIndex - 1], path[baseIndex - 0]
            );

            path.coordinates.insert(baseIndex - 1,_pointToLatLng(spline.percentage(50)));
        }

        // Check if there is a remaining gap between the last two elements - close it
        // Could be because of reminder from path divisions
        baseIndex = path.nrOfCoordinates - 1;
        if(_distance(path[baseIndex - 1],path[baseIndex]) >= stepDistance) {

            final CatmullRomSpline2D<double> spline = _createSpline(
                path[baseIndex - 1],path[baseIndex - 1],
                path[baseIndex - 0],path[baseIndex - 0]);

            path.coordinates.insert(baseIndex,_pointToLatLng(spline.percentage(50)));
        }
    }

    // Make sure we have no duplicates!
    // _removeDuplicates();
    return path;
}