double ExportFileAbstractBase::linearlyInterpolateYRadiusFromTwoPoints (double xThetaValue,
                                                                        const DocumentModelCoords &modelCoords,
                                                                        const QPointF &posGraphBefore,
                                                                        const QPointF &posGraph) const
{
    // X coordinate scaling is linear or log
    double s;
    if (modelCoords.coordScaleXTheta() == COORD_SCALE_LINEAR) {
        s = (xThetaValue - posGraphBefore.x()) / (posGraph.x() - posGraphBefore.x());
    } else {
        s = (qLn (xThetaValue) - qLn (posGraphBefore.x())) / (qLn (posGraph.x()) - qLn (posGraphBefore.x()));
    }

    // Y coordinate scaling is linear or log
    double yRadius;
    if (modelCoords.coordScaleYRadius() == COORD_SCALE_LINEAR) {
        yRadius = (1.0 - s) * posGraphBefore.y() + s * posGraph.y();
    } else {
        yRadius = qExp ((1.0 - s) * qLn (posGraphBefore.y()) + s * qLn (posGraph.y()));
    }

    return yRadius;
}
示例#2
0
void Checker::createSide (int pointRadius,
                          const QList<Point> &points,
                          const DocumentModelCoords &modelCoords,
                          double xFrom,
                          double yFrom,
                          double xTo,
                          double yTo,
                          const Transformation &transformation,
                          SideSegments &sideSegments)
{
  LOG4CPP_INFO_S ((*mainCat)) << "Checker::createSide"
                              << " pointRadius=" << pointRadius
                              << " xFrom=" << xFrom
                              << " yFrom=" << yFrom
                              << " xTo=" << xTo
                              << " yTo=" << yTo
                              << " transformation=" << transformation;

  // Originally a complicated algorithm tried to intercept a straight line from (xFrom,yFrom) to (xTo,yTo). That did not work well since:
  // 1) Calculations for mostly orthogonal cartesian coordinates worked less well with non-orthogonal polar coordinates
  // 2) Ambiguity in polar coordinates between the shorter and longer paths between (theta0,radius) and (theta1,radius)
  //
  // Current algorithm breaks up the interval between (xMin,yMin) and (xMax,yMax) into many smaller pieces and stitches the
  // desired pieces together. For straight lines in linear graphs this algorithm is very much overkill, but there is no significant
  // penalty and this approach works in every situation

  // Should give single-pixel resolution on most images, and 'good enough' resolution on extremely large images
  const int NUM_STEPS = 1000;

  bool stateSegmentIsActive = false;
  QPointF posStartScreen (0, 0);

  // Loop through steps. Final step i=NUM_STEPS does final processing if a segment is active
  for (int i = 0; i <= NUM_STEPS; i++) {

    double s = (double) i / (double) NUM_STEPS;

    // Interpolate coordinates assuming normal linear scaling
    double xGraph = (1.0 - s) * xFrom + s * xTo;
    double yGraph = (1.0 - s) * yFrom + s * yTo;

    // Replace interpolated coordinates using log scaling if appropriate, preserving the same ranges
    if (modelCoords.coordScaleXTheta() == COORD_SCALE_LOG) {
      xGraph = qExp ((1.0 - s) * qLn (xFrom) + s * qLn (xTo));
    }
    if (modelCoords.coordScaleYRadius() == COORD_SCALE_LOG) {
      yGraph = qExp ((1.0 - s) * qLn (yFrom) + s * qLn (yTo));
    }

    QPointF pointScreen;
    transformation.transformRawGraphToScreen (QPointF (xGraph, yGraph),
                                              pointScreen);

    double distanceToNearestPoint = minScreenDistanceFromPoints (pointScreen,
                                                                 points);
    if ((distanceToNearestPoint < pointRadius) ||
        (i == NUM_STEPS)) {

        // Too close to point, so point is not included in side. Or this is the final iteration of the loop
      if (stateSegmentIsActive) {

        // State transition
        finishActiveSegment (modelCoords,
                             posStartScreen,
                             pointScreen,
                             yFrom,
                             yTo,
                             transformation,
                             sideSegments);
        stateSegmentIsActive = false;

      }
    } else {

      // Outside point, so include point in side
      if (!stateSegmentIsActive) {

        // State transition
        stateSegmentIsActive = true;
        posStartScreen = pointScreen;

      }
    }
  }
}