private PatternResult calculateMatch(
      List<Section> matchedSections,
      List<Section> querySections,
      PatternContext queryCtx,
      boolean partialQuery) {
    PatternCalculationResult pointsMatchRes =
        calculatePointsMatch(querySections, matchedSections, partialQuery);
    if (pointsMatchRes == null || pointsMatchRes.getMatchedPoints().isEmpty()) {
      return null;
    }
    if (pointsMatchRes.getMatch() > queryCtx.getThreshold()) {
      return null;
    }
    if (partialQuery) {
      PatternResult result = new PatternResult();
      result.setMatch(pointsMatchRes.getMatch());
      return result;
    }

    List<Point> matchedPts = pointsMatchRes.getMatchedPoints();
    double minPos = matchedPts.get(0).getX();
    double maxPos = matchedPts.get(matchedPts.size() - 1).getX();
    double matchSize = (maxPos - minPos) / queryCtx.getDatasetSize();
    double matchPos = ((maxPos + minPos) / 2) / queryCtx.getDatasetSize();
    Long matchTimeSpan =
        Math.round(matchedPts.get(matchedPts.size() - 1).getOrigX() - matchedPts.get(0).getOrigX());

    if (this.queryHeight != null) {
      if (!checkQueryHeight(calculateMatchHeight(matchedPts))) {
        return null;
      }
    }

    PatternResult result = new PatternResult();
    result.setMatch(pointsMatchRes.getMatch());
    result.setPoints(matchedPts);
    result.setSize(matchSize);
    result.setMatchPos(matchPos);
    result.setTimespan(matchTimeSpan);
    result.setMinPos(minPos);
    result.setMaxPos(maxPos);
    result.setSections(matchedSections);

    return result;
  }
Given a list of tangents it divides the list of tangents in a list of sections. Each section
shares the same tangent signs (a section could be an increasing curve or a decreasing curve,
but not both)

@return Array of sections.
library-udf/src/main/java/org/apache/iotdb/library/match/PatternExecutor.java