public void testGetCoordinatesBetweenNonStrict() {
    try {
      CoordinateSequenceComparator coordCompare = new CoordinateSequenceComparator();
      MCoordinate mc0 = MCoordinate.create2dWithMeasure(0.0, 0.0, 0);
      MCoordinate mc1 = MCoordinate.create2dWithMeasure(0.0, 1.0, 1);
      MCoordinate mc2_1 = MCoordinate.create2dWithMeasure(0.0, 2.0, 1);
      MCoordinate mc2 = MCoordinate.create2dWithMeasure(0.0, 2.0, 2);
      MCoordinate mc3 = MCoordinate.create2dWithMeasure(0.0, 3.0, 3);
      MCoordinate mc4 = MCoordinate.create2dWithMeasure(0.0, 4.0, 4);

      // Test non-strict sequence where all coordinate x,y positions are
      // unique, but contains a
      // duplicate measure. The measure sequence in this testsuite-suite s
      // [0,1,1,3,4]
      MLineString nonStrictPointLine =
          mgeomFactory.createMLineString(new MCoordinate[] {mc0, mc1, mc2_1, mc3, mc4});
      CoordinateSequence[] nonStrictSeq = nonStrictPointLine.getCoordinatesBetween(mc0.m, mc2_1.m);
      assertNotNull(nonStrictSeq);

      nonStrictSeq = nonStrictPointLine.getCoordinatesBetween(mc0.m, mc4.m);
      assertNotNull(nonStrictSeq);

      nonStrictSeq = nonStrictPointLine.getCoordinatesBetween(mc1.m, mc4.m);
      assertNotNull(nonStrictSeq);

      nonStrictSeq = nonStrictPointLine.getCoordinatesBetween(1.1D, mc4.m);
      assertNotNull(nonStrictSeq);

    } catch (MGeometryException e) {
      e.printStackTrace();
    }
  }
  public void testReverseMeasures() {

    nullLine.reverseMeasures();

    arbitraryLine.measureOnLength(false);
    arbitraryLine.reverseMeasures();
    assertTrue(arbitraryLine.getMeasureDirection() == MGeometry.DECREASING);
    double mlast = arbitraryLine.getMatN(arbitraryLine.getNumPoints() - 1);
    arbitraryLine.reverseMeasures();
    assertTrue(arbitraryLine.getMeasureDirection() == MGeometry.INCREASING);
    double mfirst = arbitraryLine.getMatN(0);
    assertEquals(mlast, mfirst, DoubleComparator.defaultNumericalPrecision());
  }
 public void testmeasureOnLength() {
   arbitraryLine.measureOnLength(false);
   double maxM = arbitraryLine.getMaxM();
   double minM = arbitraryLine.getMinM();
   assertEquals(maxM, arbitraryLine.getLength(), DoubleComparator.defaultNumericalPrecision());
   assertEquals(minM, 0.0d, DoubleComparator.defaultNumericalPrecision());
   MCoordinate mco = (MCoordinate) arbitraryLine.getCoordinateN(arbitraryLine.getNumPoints() - 1);
   assertEquals(mco.m, maxM, DoubleComparator.defaultNumericalPrecision());
   mco = (MCoordinate) arbitraryLine.getCoordinateN(0);
   assertEquals(mco.m, minM, DoubleComparator.defaultNumericalPrecision());
 }
  public void testClone() {
    MLineString mltest = (MLineString) arbitraryLine.clone();

    Coordinate[] testco = mltest.getCoordinates();
    Coordinate[] arco = arbitraryLine.getCoordinates();
    assertEquals(testco.length, arco.length);
    for (int i = 0; i < arco.length; i++) {
      // clones must have equal, but not identical coordinates
      assertEquals(arco[i], testco[i]);
      assertNotSame(arco[i], testco[i]);
    }

    mltest = (MLineString) nullLine.clone();
    assertEquals(mltest.isEmpty(), nullLine.isEmpty());
    assertTrue(mltest.isEmpty());
  }
  public void testGetCoordinateAtM() {
    // what if null string
    try {
      Coordinate mc = nullLine.getCoordinateAtM(2);
      assertNull(mc);

      // get two neighbouring points along the arbitraryline
      arbitraryLine.measureOnLength(false);
      int elem1Indx = (int) (Math.random() * (arbitraryLine.getNumPoints() - 1));
      int elem2Indx = 0;
      if (elem1Indx == arbitraryLine.getNumPoints() - 1) {
        elem2Indx = elem1Indx - 1;
      } else {
        elem2Indx = elem1Indx + 1;
      }

      // if m is value of a coordinate, the returned coordinate should
      // equal that coordinate

      MCoordinate mco1 = (MCoordinate) arbitraryLine.getCoordinateN(elem1Indx);
      MCoordinate mcotest = (MCoordinate) arbitraryLine.getCoordinateAtM(mco1.m);
      assertNotSame(mco1, mcotest);
      assertEquals(mco1.x, mcotest.x, Math.ulp(100 * mco1.x));
      assertEquals(mco1.y, mcotest.y, Math.ulp(100 * mco1.y));
      assertEquals(mco1.m, mcotest.m, Math.ulp(100 * mco1.m));

      MCoordinate mco2 = (MCoordinate) arbitraryLine.getCoordinateN(elem2Indx);
      double offset = Math.random();
      double newM = mco1.m + offset * (mco2.m - mco1.m);
      MCoordinate mcexp =
          new MCoordinate(
              mco1.x + offset * (mco2.x - mco1.x),
              mco1.y + offset * (mco2.y - mco1.y),
              Double.NaN,
              mco1.m + offset * (mco2.m - mco1.m));
      MCoordinate mctest = (MCoordinate) arbitraryLine.getCoordinateAtM(newM);
      assertEquals(mcexp.x, mctest.x, 0.0001);
      assertEquals(mcexp.y, mctest.y, 0.0001);
      assertEquals(mcexp.m, mctest.m, 0.0001);

    } catch (Exception e) {
      System.err.println(e);
    }
  }
  public void testGetMatCoordinate() {
    try {
      // what in case of the null string
      assertTrue(Double.isNaN(nullLine.getMatCoordinate(new Coordinate(1.0, 1.0), 1.0)));

      // get two neighbouring points along the arbitraryline
      arbitraryLine.measureOnLength(false);
      int elem1Indx = (int) (Math.random() * (arbitraryLine.getNumPoints() - 1));
      int elem2Indx = 0;
      if (elem1Indx == arbitraryLine.getNumPoints() - 1) {
        elem2Indx = elem1Indx - 1;
      } else {
        elem2Indx = elem1Indx + 1;
      }

      // if a coordinate of the geometry is passed, it should return
      // exactly that m-value
      MCoordinate mco1 = (MCoordinate) arbitraryLine.getCoordinateN(elem1Indx);
      double m = arbitraryLine.getMatCoordinate(mco1, 0.00001);
      assertEquals(mco1.m, m, DoubleComparator.defaultNumericalPrecision());

      // check for a coordinate between mco1 and mco2 (neighbouring
      // coordinates)
      MCoordinate mco2 = (MCoordinate) arbitraryLine.getCoordinateN(elem2Indx);
      double offset = Math.random();
      double expectedM = mco1.m + offset * (mco2.m - mco1.m);
      Coordinate mctest =
          new Coordinate(mco1.x + offset * (mco2.x - mco1.x), mco1.y + offset * (mco2.y - mco1.y));

      double testM = arbitraryLine.getMatCoordinate(mctest, offset);
      assertEquals(expectedM, testM, DoubleComparator.defaultNumericalPrecision());
    } catch (Exception e) {
      e.printStackTrace();
      assertTrue(false); // should never reach here
    }
  }
  public void testIsMonotone() {
    MCoordinate mc0NaN = MCoordinate.create2d(1.0, 0.0);
    MCoordinate mc0 = MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0);
    MCoordinate mc1NaN = MCoordinate.create2d(1.0, 0.0);
    MCoordinate mc1 = MCoordinate.create2dWithMeasure(1.0, 0.0, 1.0);
    MCoordinate mc2NaN = MCoordinate.create2d(2.0, 0.0);
    MCoordinate mc2 = MCoordinate.create2dWithMeasure(2.0, 0.0, 2.0);
    MCoordinate mc3NaN = MCoordinate.create2d(3.0, 0.0);
    MCoordinate mc3 = MCoordinate.create2dWithMeasure(3.0, 0.0, 3.0);

    MLineString emptyLine = mgeomFactory.createMLineString(new MCoordinate[] {});
    MLineString orderedLine =
        mgeomFactory.createMLineString(new MCoordinate[] {mc0, mc1, mc2, mc3});
    MLineString unorderedLine =
        mgeomFactory.createMLineString(new MCoordinate[] {mc0, mc2, mc1, mc3});
    MLineString constantLine =
        mgeomFactory.createMLineString(new MCoordinate[] {mc2, mc2, mc2, mc2});
    MLineString reverseOrderedLine =
        mgeomFactory.createMLineString(new MCoordinate[] {mc3, mc2, mc1, mc0});
    MLineString reverseUnOrderedLine =
        mgeomFactory.createMLineString(new MCoordinate[] {mc3, mc1, mc2, mc0});
    MLineString dupCoordLine =
        mgeomFactory.createMLineString(new MCoordinate[] {mc0, mc1, mc1, mc2});
    MLineString reverseDupCoordLine =
        mgeomFactory.createMLineString(new MCoordinate[] {mc2, mc1, mc1, mc0});

    assertTrue(emptyLine.isMonotone(false));
    assertTrue(emptyLine.isMonotone(true));

    assertTrue(orderedLine.isMonotone(false));
    assertTrue(orderedLine.isMonotone(true));
    // testsuite-suite reversing the ordered line
    orderedLine.reverseMeasures();
    assertTrue(orderedLine.isMonotone(false));
    assertTrue(orderedLine.isMonotone(true));
    // testsuite-suite shifting
    orderedLine.shiftMeasure(1.0);
    assertTrue(orderedLine.isMonotone(false));
    assertTrue(orderedLine.isMonotone(true));
    orderedLine.shiftMeasure(-1.0);
    assertTrue(orderedLine.isMonotone(false));
    assertTrue(orderedLine.isMonotone(true));

    assertFalse(unorderedLine.isMonotone(false));
    assertFalse(unorderedLine.isMonotone(true));

    assertTrue(constantLine.isMonotone(false));
    assertFalse(constantLine.isMonotone(true));
    // testsuite-suite shifting
    constantLine.shiftMeasure(1.0);
    assertTrue(constantLine.isMonotone(false));
    assertFalse(constantLine.isMonotone(true));
    constantLine.shiftMeasure(-1.0);
    assertTrue(constantLine.isMonotone(false));
    assertFalse(constantLine.isMonotone(true));

    assertTrue(reverseOrderedLine.isMonotone(false));
    assertTrue(reverseOrderedLine.isMonotone(true));
    // testsuite-suite reversing the line
    reverseOrderedLine.reverseMeasures();
    assertTrue(reverseOrderedLine.isMonotone(false));
    assertTrue(reverseOrderedLine.isMonotone(true));
    // testsuite-suite shifting
    reverseOrderedLine.shiftMeasure(1.0);
    assertTrue(reverseOrderedLine.isMonotone(false));
    assertTrue(reverseOrderedLine.isMonotone(true));
    reverseOrderedLine.shiftMeasure(-1.0);
    assertTrue(reverseOrderedLine.isMonotone(false));
    assertTrue(reverseOrderedLine.isMonotone(true));

    assertFalse(reverseUnOrderedLine.isMonotone(false));
    assertFalse(reverseUnOrderedLine.isMonotone(true));

    assertTrue(dupCoordLine.isMonotone(false));
    assertFalse(dupCoordLine.isMonotone(true));
    // testsuite-suite shifting
    dupCoordLine.shiftMeasure(1.0);
    assertTrue(dupCoordLine.isMonotone(false));
    assertFalse(dupCoordLine.isMonotone(true));
    dupCoordLine.shiftMeasure(-1.0);
    assertTrue(dupCoordLine.isMonotone(false));
    assertFalse(dupCoordLine.isMonotone(true));

    assertTrue(reverseDupCoordLine.isMonotone(false));
    assertFalse(reverseDupCoordLine.isMonotone(true));
    // testsuite-suite shifting
    reverseDupCoordLine.shiftMeasure(1.0);
    assertTrue(reverseDupCoordLine.isMonotone(false));
    assertFalse(reverseDupCoordLine.isMonotone(true));
    reverseDupCoordLine.shiftMeasure(-1.0);
    assertTrue(reverseDupCoordLine.isMonotone(false));
    assertFalse(reverseDupCoordLine.isMonotone(true));

    assertEquals(orderedLine.getMeasureDirection(), MGeometry.INCREASING);
    assertEquals(unorderedLine.getMeasureDirection(), MGeometry.NON_MONOTONE);
    assertEquals(reverseOrderedLine.getMeasureDirection(), MGeometry.DECREASING);
    assertEquals(dupCoordLine.getMeasureDirection(), MGeometry.INCREASING);
    assertEquals(reverseDupCoordLine.getMeasureDirection(), MGeometry.DECREASING);

    // Test scenario where there are NaN middle measures
    MLineString internalNaNLine =
        mgeomFactory.createMLineString(new MCoordinate[] {mc0, mc1NaN, mc2NaN, mc3});
    MLineString beginNaNLine = mgeomFactory.createMLineString(new MCoordinate[] {mc0NaN, mc2, mc3});
    MLineString endNaNLine = mgeomFactory.createMLineString(new MCoordinate[] {mc0, mc2, mc3NaN});
    MLineString beginEndNaNLine =
        mgeomFactory.createMLineString(new MCoordinate[] {mc0NaN, mc2, mc3NaN});

    assertFalse(internalNaNLine.isMonotone(false));
    assertFalse(internalNaNLine.isMonotone(true));
    internalNaNLine.measureOnLength(false);
    assertTrue(internalNaNLine.isMonotone(false));
    assertTrue(internalNaNLine.isMonotone(true));

    assertFalse(beginNaNLine.isMonotone(false));
    assertFalse(beginNaNLine.isMonotone(true));
    beginNaNLine.measureOnLength(false);
    assertTrue(beginNaNLine.isMonotone(false));
    assertTrue(beginNaNLine.isMonotone(true));

    assertFalse(endNaNLine.isMonotone(false));
    assertFalse(endNaNLine.isMonotone(true));
    endNaNLine.measureOnLength(false);
    assertTrue(endNaNLine.isMonotone(false));
    assertTrue(endNaNLine.isMonotone(true));

    assertFalse(beginEndNaNLine.isMonotone(false));
    assertFalse(beginEndNaNLine.isMonotone(true));
    beginEndNaNLine.measureOnLength(false);
    assertTrue(beginEndNaNLine.isMonotone(false));
    assertTrue(beginEndNaNLine.isMonotone(true));
  }
  public void testInterpolate() {
    MCoordinate mc0NaN = MCoordinate.create2d(0.0, 0.0);
    MCoordinate mc0 = MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0);
    MCoordinate mc2NaN = MCoordinate.create2d(2.0, 0.0);
    MCoordinate mc5NaN = MCoordinate.create2d(5.0, 0.0);
    MCoordinate mc10NaN = MCoordinate.create2d(10.0, 0.0);
    MCoordinate mc10 = MCoordinate.create2dWithMeasure(10.0, 0.0, 10.0);

    // Internal coordinate measures are not defined, outer measures are
    // 0-10, total 2d length is 10
    MLineString line =
        mgeomFactory.createMLineString(new MCoordinate[] {mc0, mc2NaN, mc5NaN, mc10});
    MLineString lineBeginNaN =
        mgeomFactory.createMLineString(new MCoordinate[] {mc0NaN, mc2NaN, mc5NaN, mc10});
    MLineString lineEndNaN =
        mgeomFactory.createMLineString(new MCoordinate[] {mc0, mc2NaN, mc5NaN, mc10NaN});

    assertTrue(DoubleComparator.equals(line.getLength(), 10));
    assertTrue(DoubleComparator.equals(lineBeginNaN.getLength(), 10));
    assertTrue(DoubleComparator.equals(lineEndNaN.getLength(), 10));

    line.interpolate(mc0.m, mc10.m);
    lineBeginNaN.interpolate(mc0.m, mc10.m);
    lineEndNaN.interpolate(mc0.m, mc10.m);

    assertTrue(line.isMonotone(false));
    assertTrue(line.isMonotone(true));
    assertTrue(lineBeginNaN.isMonotone(false));
    assertTrue(lineBeginNaN.isMonotone(true));
    assertTrue(lineEndNaN.isMonotone(false));
    assertTrue(lineEndNaN.isMonotone(true));

    double[] expectedM = new double[] {mc0.m, 2.0, 5.0, mc10.m};
    for (int i = 0; i < expectedM.length; i++) {
      double actualMLine = line.getCoordinateSequence().getOrdinate(i, CoordinateSequence.M);
      double actualBeginNaN =
          lineBeginNaN.getCoordinateSequence().getOrdinate(i, CoordinateSequence.M);
      double actualEndNaN = lineEndNaN.getCoordinateSequence().getOrdinate(i, CoordinateSequence.M);
      assertTrue(DoubleComparator.equals(expectedM[i], actualMLine));
      assertTrue(DoubleComparator.equals(expectedM[i], actualBeginNaN));
      assertTrue(DoubleComparator.equals(expectedM[i], actualEndNaN));
    }

    // Test Continuous case by interpolating with begin and end measures
    // equal
    double continuousMeasure = 0.0D;
    line.interpolate(continuousMeasure, continuousMeasure);
    double[] measures = line.getMeasures();
    for (int i = 0; i < measures.length; i++)
      assertTrue(DoubleComparator.equals(measures[i], continuousMeasure));
  }
  public void testGetMeasureDirection() {
    assertTrue(nullLine.isMonotone(false));

    assertTrue(
        arbitraryLine.isMonotone(false)
            || (!arbitraryLine.isMonotone(false)
                && arbitraryLine.getMeasureDirection() == MGeometry.NON_MONOTONE));
    arbitraryLine.measureOnLength(false);
    assertEquals(MGeometry.INCREASING, arbitraryLine.getMeasureDirection());

    arbitraryLine.reverseMeasures();
    assertEquals(MGeometry.DECREASING, arbitraryLine.getMeasureDirection());

    for (int i = 0; i < arbitraryLine.getNumPoints(); i++) {
      arbitraryLine.setMeasureAtIndex(i, 0.0);
    }
    assertEquals(MGeometry.CONSTANT, arbitraryLine.getMeasureDirection());
  }
  public void testGetCoordinatesBetween() {

    try {
      // what if the null value is passed
      CoordinateSequence[] cs = nullLine.getCoordinatesBetween(0.0, 5.0);
      assertTrue("cs.length = " + cs.length + ". Should be 1", cs.length == 1);
      assertEquals(cs[0].size(), 0);

      arbitraryLine.measureOnLength(false);
      // what if from/to is outside of the range of values
      double maxM = arbitraryLine.getMaxM();
      cs = arbitraryLine.getCoordinatesBetween(maxM + 1.0, maxM + 10.0);

      // check for several ascending M-values
      int minIdx = (int) (Math.random() * (arbitraryLine.getNumPoints() - 1));
      int maxIdx = Math.min((arbitraryLine.getNumPoints() - 1), minIdx + 10);
      double minM = ((MCoordinate) arbitraryLine.getCoordinateN(minIdx)).m;
      maxM = ((MCoordinate) arbitraryLine.getCoordinateN(maxIdx)).m;
      cs = arbitraryLine.getCoordinatesBetween(minM, maxM);
      assertNotNull(cs);
      assertTrue(cs.length > 0);
      Coordinate[] coar = cs[0].toCoordinateArray();
      int j = 0;
      for (int i = minIdx; i <= maxIdx; i++) {
        assertEquals((MCoordinate) arbitraryLine.getCoordinateN(i), coar[j]);
        j++;
      }

      minM = Math.max(0.0, minM - Math.random() * 10);
      cs = arbitraryLine.getCoordinatesBetween(minM, maxM);
      coar = cs[0].toCoordinateArray();
      MCoordinate mctest = (MCoordinate) coar[0];
      MCoordinate mcexp = (MCoordinate) arbitraryLine.getCoordinateAtM(minM);
      assertEquals(mcexp, mctest);
      assertEquals(mctest.m, minM, DoubleComparator.defaultNumericalPrecision());

      maxM = Math.min(arbitraryLine.getLength(), maxM + Math.random() * 10);
      cs = arbitraryLine.getCoordinatesBetween(minM, maxM);
      coar = cs[0].toCoordinateArray();
      mctest = (MCoordinate) coar[coar.length - 1];
      mcexp = (MCoordinate) arbitraryLine.getCoordinateAtM(maxM);
      assertEquals(mcexp.x, mctest.x, Math.ulp(mcexp.x) * 100);
      assertEquals(mcexp.y, mctest.y, Math.ulp(mcexp.y) * 100);
      assertEquals(mctest.m, maxM, DoubleComparator.defaultNumericalPrecision());

    } catch (Exception e) {
      e.printStackTrace();
      assertTrue(false); // should never reach here
    }
  }
 public void testGetGeometryType() {
   assertEquals("MLineString", arbitraryLine.getGeometryType());
 }
  public void testGetClosestPoint() {

    try {
      if (!arbitraryLine.isMonotone(false)) {
        Coordinate mc = arbitraryLine.getClosestPoint(new Coordinate(1.0, 2.0), 0.1);
        assertTrue(false); // should never evaluate this
      }
    } catch (Exception e) {
      assertTrue(
          ((MGeometryException) e).getType() == MGeometryException.OPERATION_REQUIRES_MONOTONE);
    }

    try {
      // check reaction on null string
      MCoordinate mc = nullLine.getClosestPoint(new Coordinate(0.0, 1.0), 1.0);
      assertNull(mc);

      // must return the very same coordinate if the coordinate is a
      // coordinate of the line
      arbitraryLine.measureOnLength(false);
      int selp = (int) (arbitraryLine.getNumPoints() / 2);
      MCoordinate mcexp = (MCoordinate) arbitraryLine.getCoordinateN(selp);
      MCoordinate mctest = arbitraryLine.getClosestPoint(mcexp, 1);
      assertEquals(mcexp, mctest);

      // must not return a point that is beyond the tolerance
      mctest = controlledLine.getClosestPoint(new Coordinate(20.0, 20, 0), 1.0);
      assertNull(mctest);

      // check for cases of circular MGeometry: lowest measure should be
      // return.
      ringLine.measureOnLength(false);
      assertTrue(ringLine.isRing());
      assertTrue(ringLine.isMonotone(false));
      assertTrue(ringLine.getMeasureDirection() == MGeometry.INCREASING);
      MCoordinate expCo = MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0);
      MCoordinate testCo = ringLine.getClosestPoint(expCo, 0.1);
      assertTrue(DoubleComparator.equals(testCo.m, expCo.m));
      ringLine.reverseMeasures();
      testCo = ringLine.getClosestPoint(expCo, 0.1);
      assertTrue(DoubleComparator.equals(testCo.m, expCo.m));
      ringLine.measureOnLength(false);
      int n = ringLine.getNumPoints() - 1;
      ringLine.setMeasureAtIndex(n, 100.0);
      ringLine.setMeasureAtIndex(0, 0.0);
      testCo = ringLine.getClosestPoint(expCo, 0.001);
      assertTrue(DoubleComparator.equals(testCo.m, 0.0));

      // get two neighbouring points along the arbitraryline
      arbitraryLine.measureOnLength(false);
      int elem1Indx = (int) (Math.random() * (arbitraryLine.getNumPoints() - 1));
      int elem2Indx = 0;
      if (elem1Indx == arbitraryLine.getNumPoints() - 1) {
        elem2Indx = elem1Indx - 1;
      } else {
        elem2Indx = elem1Indx + 1;
      }
      // testsuite-suite whether a coordinate between these two returns exactly
      MCoordinate mco1 = (MCoordinate) arbitraryLine.getCoordinateN(elem1Indx);
      MCoordinate mco2 = (MCoordinate) arbitraryLine.getCoordinateN(elem2Indx);
      double d = mco1.distance(mco2);
      double offset = Math.random();
      mcexp =
          MCoordinate.create2dWithMeasure(
              mco1.x + offset * (mco2.x - mco1.x), mco1.y + offset * (mco2.y - mco1.y), 0.0);
      mctest = arbitraryLine.getClosestPoint(mcexp, d);
      mcexp.m = mco1.m + offset * (mco2.m - mco1.m);
      assertEquals(mcexp.x, mctest.x, 0.001);
      assertEquals(mcexp.y, mctest.y, 0.001);
      assertEquals(mcexp.z, mctest.z, 0.001);
      double delta = Math.random();

      MCoordinate mcin =
          MCoordinate.create2dWithMeasure(
              mco1.x + offset * (mco2.x - mco1.x) + delta,
              mco1.y + offset * (mco2.y - mco1.y) + delta,
              0.0);

      // returned point is on the line
      mctest = arbitraryLine.getClosestPoint(mcin, d);
      assertEquals(mcin.x, mctest.x, delta * Math.sqrt(2));
      assertEquals(mcin.y, mctest.y, delta * Math.sqrt(2));
    } catch (Exception e) {
      e.printStackTrace();
      assertTrue(false); // should never reach this point
    }
  }