void buildPaths()

in web/github_dataviz/lib/layered_chart.dart [35:163]


  void buildPaths(
      Size size,
      List<DataSeries> dataToPlot,
      List<WeekLabel> milestones,
      int numPoints,
      double graphGap,
      double margin,
      double capTheta,
      double capSize) {
    double screenRatio = size.width / size.height;
    double degrees = MathUtils.clampedMap(screenRatio, 0.5, 2.5, 50, 5);
    theta = pi * degrees / 180;
    graphHeight = MathUtils.clampedMap(screenRatio, 0.5, 2.5, 50, 150);

    int m = dataToPlot.length;
    paths = [];
    capPaths = [];
    maxValues = [];
    for (int i = 0; i < m; i++) {
      int n = dataToPlot[i].series.length;
      maxValues.add(0);
      for (int j = 0; j < n; j++) {
        double v = dataToPlot[i].series[j].toDouble();
        if (v > maxValues[i]) {
          maxValues[i] = v;
        }
      }
    }
    double totalGap = m * graphGap;
    double xIndent = totalGap / tan(capTheta);
    double startX = margin + xIndent;
    double endX = size.width - margin;
    double startY = size.height;
    double endY = startY - (endX - startX) * tan(theta);
    double xWidth = (endX - startX) / numPoints;
    double capRangeX = capSize * cos(capTheta);
    double tanCapTheta = tan(capTheta);
    final curvePoints = <double>[];
    for (int i = 0; i < m; i++) {
      List<int> series = dataToPlot[i].series;
      int n = series.length;
      final controlPoints = <Point2D>[];
      controlPoints.add(Point2D(-1, 0));
      double last = 0;
      for (int j = 0; j < n; j++) {
        double v = series[j].toDouble();
        controlPoints.add(Point2D(j.toDouble(), v));
        last = v;
      }
      controlPoints.add(Point2D(n.toDouble(), last));
      CatmullInterpolator curve = CatmullInterpolator(controlPoints);
      ControlPointAndValue cpv = ControlPointAndValue();
      for (int j = 0; j < numPoints; j++) {
        cpv.value = MathUtils.map(
            j.toDouble(), 0, (numPoints - 1).toDouble(), 0, (n - 1).toDouble());
        curve.progressiveGet(cpv);
        curvePoints.add(MathUtils.map(
            max(0, cpv.value!), 0, maxValues[i].toDouble(), 0, graphHeight));
      }
      paths.add(Path());
      capPaths.add(Path());
      paths[i].moveTo(startX, startY);
      capPaths[i].moveTo(startX, startY);
      for (int j = 0; j < numPoints; j++) {
        double v = curvePoints[j];
        int k = j + 1;
        double xDist = xWidth;
        double capV = v;
        while (k < numPoints && xDist <= capRangeX) {
          double cy = curvePoints[k] + xDist * tanCapTheta;
          capV = max(capV, cy);
          k++;
          xDist += xWidth;
        }
        double x = MathUtils.map(
            j.toDouble(), 0, (numPoints - 1).toDouble(), startX, endX);
        double baseY = MathUtils.map(
            j.toDouble(), 0, (numPoints - 1).toDouble(), startY, endY);
        double y = baseY - v;
        double cY = baseY - capV;
        paths[i].lineTo(x, y);
        if (j == 0) {
          int k = capRangeX ~/ xWidth;
          double mx = MathUtils.map(
              -k.toDouble(), 0, (numPoints - 1).toDouble(), startX, endX);
          double my = MathUtils.map(
                  -k.toDouble(), 0, (numPoints - 1).toDouble(), startY, endY) -
              capV;
          capPaths[i].lineTo(mx, my);
        }
        capPaths[i].lineTo(x, cY);
      }
      paths[i].lineTo(endX, endY);
      paths[i].lineTo(endX, endY + 1);
      paths[i].lineTo(startX, startY + 1);
      paths[i].close();
      capPaths[i].lineTo(endX, endY);
      capPaths[i].lineTo(endX, endY + 1);
      capPaths[i].lineTo(startX, startY + 1);
      capPaths[i].close();
    }
    labelPainter = [];
    for (int i = 0; i < dataToPlot.length; i++) {
      TextSpan span = TextSpan(
          style: const TextStyle(
              color: Color.fromARGB(255, 255, 255, 255), fontSize: 12),
          text: dataToPlot[i].label.toUpperCase());
      TextPainter tp = TextPainter(
          text: span,
          textAlign: TextAlign.left,
          textDirection: TextDirection.ltr);
      tp.layout();
      labelPainter.add(tp);
    }
    milestonePainter = [];
    for (int i = 0; i < milestones.length; i++) {
      TextSpan span = TextSpan(
          style: const TextStyle(
              color: Color.fromARGB(255, 255, 255, 255), fontSize: 10),
          text: milestones[i].label.toUpperCase());
      TextPainter tp = TextPainter(
          text: span,
          textAlign: TextAlign.left,
          textDirection: TextDirection.ltr);
      tp.layout();
      milestonePainter.add(tp);
    }
    lastSize = Size(size.width, size.height);
  }