@Override
  public boolean containsPoint(FGEPoint p) {
    if ((p.x >= getX() - EPSILON)
        && (p.x <= getX() + getWidth() + EPSILON)
        && (p.y >= getY() - EPSILON)
        && (p.y <= getY() + getHeight() + EPSILON)) {

      if (!getIsFilled()) {
        FGESegment north = getArcExcludedNorth();
        FGESegment south = getArcExcludedSouth();
        FGESegment west = getArcExcludedWest();
        FGESegment east = getArcExcludedEast();
        return (north.contains(p)
            || south.contains(p)
            || east.contains(p)
            || west.contains(p)
            || getNorthEastRound().contains(p)
            || getNorthWestRound().contains(p)
            || getSouthEastRound().contains(p)
            || getSouthWestRound().contains(p));
      } else {
        if (new FGERectangle(
                new FGEPoint(getX(), getY() + archeight / 2),
                new FGEDimension(getWidth(), getHeight() - archeight),
                Filling.FILLED)
            .contains(p)) {
          return true;
        }
        if (new FGERectangle(
                new FGEPoint(getX() + arcwidth / 2, getY()),
                new FGEDimension(getWidth() - arcwidth, getHeight()),
                Filling.FILLED)
            .contains(p)) {
          return true;
        }
        return (getFilledNorthEastRound().containsPoint(p)
            || getFilledNorthWestRound().containsPoint(p)
            || getFilledSouthEastRound().containsPoint(p)
            || getFilledSouthWestRound().containsPoint(p));
      }
    }
    return false;
  }
  @Override
  public FGEPoint nearestOutlinePoint(FGEPoint aPoint) {
    FGEPoint returned = null;
    double distSq, minimalDistanceSq = java.lang.Double.POSITIVE_INFINITY;

    FGESegment north = getNorth();
    FGESegment south = getSouth();
    FGESegment east = getEast();
    FGESegment west = getWest();

    FGEPoint p = north.getNearestPointOnSegment(aPoint);
    distSq = FGEPoint.distanceSq(p, aPoint);
    if (distSq < minimalDistanceSq) {
      returned = p;
      minimalDistanceSq = distSq;
    }

    p = south.getNearestPointOnSegment(aPoint);
    distSq = FGEPoint.distanceSq(p, aPoint);
    if (distSq < minimalDistanceSq) {
      returned = p;
      minimalDistanceSq = distSq;
    }

    p = east.getNearestPointOnSegment(aPoint);
    distSq = FGEPoint.distanceSq(p, aPoint);
    if (distSq < minimalDistanceSq) {
      returned = p;
      minimalDistanceSq = distSq;
    }

    p = west.getNearestPointOnSegment(aPoint);
    distSq = FGEPoint.distanceSq(p, aPoint);
    if (distSq < minimalDistanceSq) {
      returned = p;
      minimalDistanceSq = distSq;
    }
    if (returned == null) {
      returned = new FGEPoint(0, 0);
    }
    if (getNorthWestRoundBounds().containsPoint(returned)) {
      // System.out.println("nearestOutlinePoint() in NW");
      return getNorthWestRound().nearestOutlinePoint(aPoint);
    }

    if (getSouthWestRoundBounds().containsPoint(returned)) {
      // System.out.println("nearestOutlinePoint() in SW");
      return getSouthWestRound().nearestOutlinePoint(aPoint);
    }

    if (getNorthEastRoundBounds().containsPoint(returned)) {
      // System.out.println("nearestOutlinePoint() in NE");
      return getNorthEastRound().nearestOutlinePoint(aPoint);
    }

    if (getSouthEastRoundBounds().containsPoint(returned)) {
      // System.out.println("nearestOutlinePoint() in SE");
      return getSouthEastRound().nearestOutlinePoint(aPoint);
    }

    return returned;
  }