computeWorldPositions method

Float32List computeWorldPositions(
  1. PathAttachment path,
  2. int spacesCount,
  3. bool tangents,
  4. bool percentPosition,
  5. bool percentSpacing,
)

Implementation

Float32List computeWorldPositions(PathAttachment path, int spacesCount,
    bool tangents, bool percentPosition, bool percentSpacing) {
  final Slot? target = this.target;
  double position = this.position;
  final Float32List spaces = this.spaces;
  final Float32List out = ArrayUtils.copyWithNewArraySize(
      positions, spacesCount * 3 + 2, double.infinity) as Float32List;
  Float32List world;
  final bool closed = path.closed;
  int verticesLength = path.worldVerticesLength,
      curveCount = verticesLength ~/ 6,
      prevCurve = PathConstraint.none;

  if (!path.constantSpeed) {
    final Float32List lengths = path.lengths;
    curveCount -= closed ? 1 : 2;
    final double pathLength = lengths[curveCount];
    if (percentPosition) position = position * pathLength;
    if (percentSpacing) {
      for (int i = 0; i < spacesCount; i++) {
        spaces[i] *= pathLength;
      }
    }
    world = ArrayUtils.copyWithNewArraySize(this.world, 8, double.infinity)
        as Float32List;
    for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) {
      final double space = spaces[i];
      position = position + space;
      double p = position;

      if (closed) {
        p %= pathLength;
        if (p < 0) p += pathLength;
        curve = 0;
      } else if (p < 0) {
        if (prevCurve != PathConstraint.before) {
          prevCurve = PathConstraint.before;
          path.computeWorldVertices(target!, 2, 4, world, 0, 2);
        }
        addBeforePosition(p, world, 0, out, o);
        continue;
      } else if (p > pathLength) {
        if (prevCurve != PathConstraint.after) {
          prevCurve = PathConstraint.after;
          path.computeWorldVertices(
              target!, verticesLength - 6, 4, world, 0, 2);
        }
        addAfterPosition(p - pathLength, world, 0, out, o);
        continue;
      }

      // Determine curve containing position.
      for (;; curve++) {
        final double length = lengths[curve];
        if (p > length) continue;
        if (curve == 0) {
          p /= length;
        } else {
          final double prev = lengths[curve - 1];
          p = (p - prev) / (length - prev);
        }
        break;
      }
      if (curve != prevCurve) {
        prevCurve = curve;
        if (closed && curve == curveCount) {
          path
            ..computeWorldVertices(
                target!, verticesLength - 4, 4, world, 0, 2)
            ..computeWorldVertices(target, 0, 4, world, 4, 2);
        } else {
          path.computeWorldVertices(target!, curve * 6 + 2, 8, world, 0, 2);
        }
      }
      addCurvePosition(
          p,
          world[0],
          world[1],
          world[2],
          world[3],
          world[4],
          world[5],
          world[6],
          world[7],
          out,
          o,
          tangents || (i > 0 && space == 0));
    }
    return out;
  }

  // World vertices.
  if (closed) {
    verticesLength += 2;
    world = ArrayUtils.copyWithNewArraySize(
        this.world, verticesLength, double.infinity) as Float32List;
    path
      ..computeWorldVertices(target!, 2, verticesLength - 4, world, 0, 2)
      ..computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2);
    world[verticesLength - 2] = world[0];
    world[verticesLength - 1] = world[1];
  } else {
    curveCount--;
    verticesLength -= 4;
    world = ArrayUtils.copyWithNewArraySize(
        this.world, verticesLength, double.infinity) as Float32List;
    path.computeWorldVertices(target!, 2, verticesLength, world, 0, 2);
  }

  // Curve lengths.
  final Float32List curves = ArrayUtils.copyWithNewArraySize(
      this.curves, curveCount, double.infinity) as Float32List;
  double pathLength = 0.0;
  double x1 = world[0],
      y1 = world[1],
      cx1 = 0.0,
      cy1 = 0.0,
      cx2 = 0.0,
      cy2 = 0.0,
      x2 = 0.0,
      y2 = 0.0;
  double tmpx = 0.0,
      tmpy = 0.0,
      dddfx = 0.0,
      dddfy = 0.0,
      ddfx = 0.0,
      ddfy = 0.0,
      dfx = 0.0,
      dfy = 0.0;
  for (int i = 0, w = 2; i < curveCount; i++, w += 6) {
    cx1 = world[w];
    cy1 = world[w + 1];
    cx2 = world[w + 2];
    cy2 = world[w + 3];
    x2 = world[w + 4];
    y2 = world[w + 5];
    tmpx = (x1 - cx1 * 2 + cx2) * 0.1875;
    tmpy = (y1 - cy1 * 2 + cy2) * 0.1875;
    dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375;
    dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375;
    ddfx = tmpx * 2 + dddfx;
    ddfy = tmpy * 2 + dddfy;
    dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667;
    dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667;
    pathLength += math.sqrt(dfx * dfx + dfy * dfy);
    dfx += ddfx;
    dfy += ddfy;
    ddfx += dddfx;
    ddfy += dddfy;
    pathLength += math.sqrt(dfx * dfx + dfy * dfy);
    dfx += ddfx;
    dfy += ddfy;
    pathLength += math.sqrt(dfx * dfx + dfy * dfy);
    dfx += ddfx + dddfx;
    dfy += ddfy + dddfy;
    pathLength += math.sqrt(dfx * dfx + dfy * dfy);
    curves[i] = pathLength;
    x1 = x2;
    y1 = y2;
  }
  if (percentPosition) position = position * pathLength;
  if (percentSpacing) {
    for (int i = 0; i < spacesCount; i++) {
      spaces[i] *= pathLength;
    }
  }

  final Float32List segments = this.segments;
  double curveLength = 0.0;
  for (int i = 0, o = 0, curve = 0, segment = 0;
      i < spacesCount;
      i++, o += 3) {
    final double space = spaces[i];
    position = position + space;
    double p = position;

    if (closed) {
      p %= pathLength;
      if (p < 0) p += pathLength;
      curve = 0;
    } else if (p < 0) {
      addBeforePosition(p, world, 0, out, o);
      continue;
    } else if (p > pathLength) {
      addAfterPosition(p - pathLength, world, verticesLength - 4, out, o);
      continue;
    }

    // Determine curve containing position.
    for (;; curve++) {
      final double length = curves[curve];
      if (p > length) continue;
      if (curve == 0) {
        p /= length;
      } else {
        final double prev = curves[curve - 1];
        p = (p - prev) / (length - prev);
      }
      break;
    }

    // Curve segment lengths.
    if (curve != prevCurve) {
      prevCurve = curve;
      int ii = curve * 6;
      x1 = world[ii];
      y1 = world[ii + 1];
      cx1 = world[ii + 2];
      cy1 = world[ii + 3];
      cx2 = world[ii + 4];
      cy2 = world[ii + 5];
      x2 = world[ii + 6];
      y2 = world[ii + 7];
      tmpx = (x1 - cx1 * 2 + cx2) * 0.03;
      tmpy = (y1 - cy1 * 2 + cy2) * 0.03;
      dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006;
      dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006;
      ddfx = tmpx * 2 + dddfx;
      ddfy = tmpy * 2 + dddfy;
      dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667;
      dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667;
      curveLength = math.sqrt(dfx * dfx + dfy * dfy);
      segments[0] = curveLength;
      for (ii = 1; ii < 8; ii++) {
        dfx += ddfx;
        dfy += ddfy;
        ddfx += dddfx;
        ddfy += dddfy;
        curveLength += math.sqrt(dfx * dfx + dfy * dfy);
        segments[ii] = curveLength;
      }
      dfx += ddfx;
      dfy += ddfy;
      curveLength += math.sqrt(dfx * dfx + dfy * dfy);
      segments[8] = curveLength;
      dfx += ddfx + dddfx;
      dfy += ddfy + dddfy;
      curveLength += math.sqrt(dfx * dfx + dfy * dfy);
      segments[9] = curveLength;
      segment = 0;
    }

    // Weight by segment length.
    p *= curveLength;
    for (;; segment++) {
      final double length = segments[segment];
      if (p > length) continue;
      if (segment == 0) {
        p /= length;
      } else {
        final double prev = segments[segment - 1];
        p = segment + (p - prev) / (length - prev);
      }
      break;
    }
    addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o,
        tangents || (i > 0 && space == 0));
  }
  return out;
}