@Override
  protected boolean operateInternal(Set<Triangle> triangles) {

    Triangle winner = random.choice(triangles);

    float perfectness =
        new BigDecimal("2").divide(winner.perfectness(), MathContext.DECIMAL128).floatValue();
    float myRate = Math.max(perfectness, rate);
    if (!random.rate(myRate)) {
      return false;
    }

    for (Triangle t : triangles) {
      if (t == winner) {
        continue;
      }
      Segment common = TriangleUtils.segmentInCommon(winner, t);
      if (common != null) {

        boolean swapped = swap(triangles, winner, t, common);
        return swapped;
      }
    }

    return false;
  }
  public static boolean swap(Set<Triangle> triangles, Triangle a, Triangle b, Segment common) {

    Point otherOfA = otherOf(a, common);
    Point otherOfB = otherOf(b, common);

    Line ab = Line.defineByPoints(otherOfA, otherOfB);
    if (ab.distance(common.getP1()).doubleValue() < 0.001
        || ab.distance(common.getP2()).doubleValue() < 0.001) {
      return false;
    }

    Triangle t1;
    Triangle t2;

    if (TriangleUtils.counterClockwise(otherOfA, otherOfB, common.getP1()) < 0) {
      t1 = new Triangle(otherOfA, otherOfB, common.getP1());
      t2 = new Triangle(otherOfA, common.getP2(), otherOfB);
    } else {
      t1 = new Triangle(otherOfB, otherOfA, common.getP1());
      t2 = new Triangle(otherOfB, common.getP2(), otherOfA);
    }

    BigDecimal oldArea = a.area().add(b.area(), DECIMAL128).setScale(MY_SCALE, MY_RND);
    BigDecimal newArea = t1.area().add(t2.area(), DECIMAL128).setScale(MY_SCALE, MY_RND);

    if (oldArea.compareTo(newArea) == 0) {
      triangles.remove(a);
      triangles.remove(b);

      triangles.add(t1);
      triangles.add(t2);

      return true;
    }

    return false;
  }