Example #1
0
  public Area getCutArea1() {

    if (alpha[1] < 0.08f) {
      // 假如这部分已经基本透明,那么就把它变成空区域,并把它的位置速度变得和area部分一样,这样下次切割就不会出错。
      cutArea1 = new Area();
      x[1] = x[0];
      y[1] = y[0];
      vx[1] = vx[0];
      vy[1] = vy[0];
      asMove2.setToIdentity();
      asMove2.translate(x[1], y[1]);
      cutArea1 = new Area(asMove2.createTransformedShape(cutArea1));
    }

    if (cutArea1.isEmpty()) {
      alpha[1] = 1f;
    } else {

      alpha[1] = alpha[1] - 0.04f;
    }
    asMove2.setToIdentity();
    x[1] = x[1] + vx[1];
    y[1] = y[1] + vy[1];

    asMove2.translate(vx[1], vy[1]);
    cutArea1 = new Area(asMove2.createTransformedShape(cutArea1));

    return sinWave(cutArea1);
  }
Example #2
0
  public Area getCutArea2() {

    if (alpha[2] < 0.08f) {
      cutArea2 = new Area();
      x[2] = x[0];
      y[2] = y[0];
      vx[2] = vx[0];
      vy[2] = vy[0];
      asMove3.setToIdentity();
      asMove3.translate(x[2], y[2]);
      cutArea2 = new Area(asMove3.createTransformedShape(cutArea2));
    }
    if (cutArea2.isEmpty()) {
      alpha[2] = 1f;

    } else {

      alpha[2] = alpha[2] - 0.04f;
    }

    asMove3.setToIdentity();
    x[2] = x[2] + vx[2];
    y[2] = y[2] + vy[2];

    asMove3.translate(vx[2], vy[2]);
    cutArea2 = new Area(asMove3.createTransformedShape(cutArea2));
    return sinWave(cutArea2);
  }
 /**
  * Test whether the given region intersects with this area.
  *
  * @param region the region to test
  * @param thisArea an area object for this region
  * @return true if the two regions intersect
  */
 protected boolean intersects(ProtectedRegion region, Area thisArea) {
   if (intersectsBoundingBox(region)) {
     Area testArea = region.toArea();
     testArea.intersect(thisArea);
     return !testArea.isEmpty();
   } else {
     return false;
   }
 }
Example #4
0
 /**
  * Method intersects area of Sensor and all VivaeObjects and returns those that have non-zero
  * intersection.
  *
  * @param objects Vector of VivaeObjects that are checked for collision with the body of Sensor.
  * @return Vector of VivaeObjects that are in collision with the body of Sensor.
  */
 public Vector<VivaeObject> getVivaesOnSight(Vector<VivaeObject> objects) {
   Vector<VivaeObject> objectsOnSight = new Vector<VivaeObject>();
   // for (VivaeObject vivaeObject : objects) {
   for (VivaeObject vivaeObject : getCloseVivaes(objects, owner.getArena().getWalls())) {
     if (vivaeObject != this.owner) {
       Area actArea = (Area) vivaeObject.getArea().clone();
       actArea.intersect(this.getArea());
       if (!actArea.isEmpty()) objectsOnSight.add(vivaeObject);
       //             if(vivaeObject instanceof roboneat.RoboNeatRobot)System.out.println("robot
       // seen by"+this.owner);
     }
   }
   return objectsOnSight;
 }
Example #5
0
 private List<ZoneLogic> overlappedRooms(ZoneLogic zone) {
   List<ZoneLogic> overlapped = new ArrayList<ZoneLogic>();
   Area currentZoneArea = new Area(TopologyUtils.convertToAWT(zone.getPojo().getShape()));
   for (Room r : currEnv.getRooms()) {
     if (!r.equals(selectedZone)) {
       Shape testZoneShape = TopologyUtils.convertToAWT(r.getPojo().getShape());
       Area testArea = new Area(testZoneShape);
       testArea.intersect(currentZoneArea);
       if (!testArea.isEmpty()) {
         overlapped.add(r);
       }
     }
   }
   return overlapped;
 }
Example #6
0
 /**
  * Returns {@code true} if the rectangle (in device space) intersects with the shape (the
  * interior, if {@code onStroke} is false, otherwise the stroked outline of the shape).
  *
  * @param rect a rectangle (in device space).
  * @param s the shape.
  * @param onStroke test the stroked outline only?
  * @return A boolean.
  */
 @Override
 public boolean hit(Rectangle rect, Shape s, boolean onStroke) {
   Shape ts;
   if (onStroke) {
     ts = this.transform.createTransformedShape(this.stroke.createStrokedShape(s));
   } else {
     ts = this.transform.createTransformedShape(s);
   }
   if (!rect.getBounds2D().intersects(ts.getBounds2D())) {
     return false;
   }
   Area a1 = new Area(rect);
   Area a2 = new Area(ts);
   a1.intersect(a2);
   return !a1.isEmpty();
 }
Example #7
0
  public static Blockade hasIntersectionWithBlockades(Pair<Integer, Integer> point, Area a) {
    double size = ReachablityConstants.AGENT_WIDTH * 1 * 6;
    if (!(a instanceof Road)) return null;
    Road road = (Road) a;
    if (!road.isBlockadesDefined()) return null;
    if (road.getBlockades().size() == 0) return null;

    Ellipse2D.Double expandHuman =
        new Ellipse2D.Double(a.getX() - size / 2, a.getY() - size / 2, size, size);
    java.awt.geom.Area area = new java.awt.geom.Area(expandHuman);
    for (Blockade b : road.getBlockades()) {
      area.intersect(new java.awt.geom.Area(b.getShape()));
      if (!area.isEmpty()) return b;
    }
    return null;
  }
Example #8
0
 public Surface getSurfaceUnderVivaeObject(VivaeObject actor) {
   Vector<Surface> surfacesActorIsOn = new Vector<Surface>();
   Surface srfc = null;
   for (Surface surface : surfaces) {
     srfc = surface;
     Area actArea = actor.getArea();
     actArea.intersect(srfc.getArea());
     if (!actArea.isEmpty()) {
       surfacesActorIsOn.add(srfc);
     }
   }
   if (surfacesActorIsOn.isEmpty()) {
     return null;
   }
   srfc = surfacesActorIsOn.get(surfacesActorIsOn.size() - 1);
   return srfc;
 }
Example #9
0
 /**
  * Returns a coefficient of the surface the VivaeObject is on or 0 if there is no surface.
  *
  * @param actor
  */
 public float getFrictionOfSurface(VivaeObject actor) {
   Vector<Surface> surfacesActorIsOn = new Vector<Surface>();
   Surface srfc;
   for (Surface surface : surfaces) {
     srfc = surface;
     Area actArea = actor.getArea();
     actArea.intersect(srfc.getArea());
     if (!actArea.isEmpty()) {
       surfacesActorIsOn.add(srfc);
     }
   }
   if (surfacesActorIsOn.isEmpty()) {
     return 0f;
   }
   srfc = surfacesActorIsOn.get(surfacesActorIsOn.size() - 1);
   return srfc.getFriction();
 }
Example #10
0
 protected static void addToDownload(
     Area a, Rectangle2D r, Collection<Rectangle2D> results, double max_area) {
   Area tmp = new Area(r);
   // intersect with sought-after area
   tmp.intersect(a);
   if (tmp.isEmpty()) {
     return;
   }
   Rectangle2D bounds = tmp.getBounds2D();
   if (bounds.getWidth() * bounds.getHeight() > max_area) {
     // the rectangle gets too large; split it and make recursive call.
     Rectangle2D r1;
     Rectangle2D r2;
     if (bounds.getWidth() > bounds.getHeight()) {
       // rectangles that are wider than high are split into a left and right half,
       r1 =
           new Rectangle2D.Double(
               bounds.getX(), bounds.getY(), bounds.getWidth() / 2, bounds.getHeight());
       r2 =
           new Rectangle2D.Double(
               bounds.getX() + bounds.getWidth() / 2,
               bounds.getY(),
               bounds.getWidth() / 2,
               bounds.getHeight());
     } else {
       // others into a top and bottom half.
       r1 =
           new Rectangle2D.Double(
               bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight() / 2);
       r2 =
           new Rectangle2D.Double(
               bounds.getX(),
               bounds.getY() + bounds.getHeight() / 2,
               bounds.getWidth(),
               bounds.getHeight() / 2);
     }
     addToDownload(a, r1, results, max_area);
     addToDownload(a, r2, results, max_area);
   } else {
     results.add(bounds);
   }
 }
Example #11
0
  /**
   * Tests if two polygons intersect.
   *
   * @param first
   * @param second
   * @return intersection kind
   */
  public static PolygonIntersection polygonIntersection(List<Node> first, List<Node> second) {

    Area a1 = getArea(first);
    Area a2 = getArea(second);

    Area inter = new Area(a1);
    inter.intersect(a2);

    Rectangle bounds = inter.getBounds();

    if (inter.isEmpty() || bounds.getHeight() * bounds.getWidth() <= 1.0) {
      return PolygonIntersection.OUTSIDE;
    } else if (inter.equals(a1)) {
      return PolygonIntersection.FIRST_INSIDE_SECOND;
    } else if (inter.equals(a2)) {
      return PolygonIntersection.SECOND_INSIDE_FIRST;
    } else {
      return PolygonIntersection.CROSSING;
    }
  }
Example #12
0
  /**
   * Returns a coefficient of the surface the VivaeObject is on or 0 if there is no surface.
   *
   * @param actor
   */
  public float getFrictionOfSurface(VivaeObject actor) {

    ArrayList<Surface> surfacesActorIsOn = new ArrayList<Surface>();
    Surface srfc;
    Area actArea = actor.getArea();

    for (Surface surface : surfaces) {
      srfc = surface;
      Area actor2intersect = (Area) actArea.clone();
      actor2intersect.intersect(srfc.getArea());
      if (!actor2intersect.isEmpty()) {
        surfacesActorIsOn.add(srfc);
      }
    }
    if (surfacesActorIsOn.isEmpty()) {
      return 0f;
    }
    srfc = surfacesActorIsOn.get(surfacesActorIsOn.size() - 1);

    float res = srfc.getFriction();
    //        System.out.println("Surface = " + srfc.getClass().toString() + " has friction " +
    // res);
    return res;
  }
Example #13
0
  /**
   * Method that provides a recursive mechanism to go through OMGraphicsLists to filter out areas,
   * inside or outside another.
   */
  protected OMGraphicList filterList(OMGraphicList omgl, Area area, boolean getInsideArea) {
    OMGraphicList ret = new OMGraphicList();
    boolean DEBUG_DETAIL = Debug.debugging("filtersupportdetail");
    boolean DEBUG = Debug.debugging("filtersupport") || DEBUG_DETAIL;

    if (DEBUG) {
      Debug.output("FilterSupport.filterList");
    }

    int count = 0; // for debugging

    if (area != null && omgl != null) { // just checking

      for (OMGraphic omg : omgl) {

        if (DEBUG) {
          Debug.output("FilterSupport.filterList evaluating " + (count++) + " OMGraphic, " + omg);
        }

        boolean outsideFilter = true;

        // If not visible, automatically fails...
        if (!omg.isVisible()) {
          if (DEBUG) {
            Debug.output("   OMGraphic not visible, ignoring");
          }
          continue;
        }

        if (omg instanceof OMGraphicList) {
          if (omg == omgl) {
            Debug.output("   OMGraphic is parent list (points to itself), ignoring...");
            continue;
          }

          if (DEBUG) {
            Debug.output("  (filterList recursiving handing OMGraphicList)");
          }

          OMGraphicList subList = filterList((OMGraphicList) omg, area, getInsideArea);

          if (!subList.isEmpty()) {
            if (DEBUG) {
              Debug.output(
                  "  +++ OMGraphicList's contents (" + subList.size() + ") pass filter, adding...");
            }

            if (((OMGraphicList) omg).isVague()) {
              passedFilter(omg);
              omg.setVisible(true);
              ret.add(omg);
            } else {
              passedFilter(subList);
              ret.add(subList);
            }
          } else {
            if (DEBUG) {
              Debug.output("  --- OMGraphicList's contents fail filter, ignoring...");
            }

            failedFilter(omg);
          }
          continue;
        } else {
          Shape omgShape = omg.getShape();
          if (omgShape != null) {
            if (omgShape.getBounds2D().getWidth() == 0 && omgShape.getBounds2D().getHeight() == 0) {
              if (area.contains(omgShape.getBounds2D().getX(), omgShape.getBounds2D().getY())) {
                if (DEBUG_DETAIL) {
                  Debug.output("   +++ omg contains position");
                }

                outsideFilter = false;
              }
            } else if (area.intersects(omgShape.getBounds2D())) {
              if (DEBUG_DETAIL) {
                Debug.output("   +++ omg intersects bounds");
              }

              // The area.interects() method above is a
              // general case. If you care about
              // preciseness, set the precise flag.
              // Depending on the performance cost, we might
              // want to make it permanent.

              if (precise) {
                Area omgArea = new Area(omgShape);
                if (!omgArea.isSingular()) {
                  Area clone = (Area) area.clone();
                  clone.intersect(omgArea);
                  if (!clone.isEmpty()) {
                    outsideFilter = false;
                  }
                } else {
                  outsideFilter = false;
                }
              } else {
                outsideFilter = false;
              }
            }
          }

          // decide what to do depending on filteredOut and
          // getInsideArea
          if ((outsideFilter && !getInsideArea) || (!outsideFilter && getInsideArea)) {

            if (DEBUG) {
              Debug.output("   +++ OMGraphic passes filter, adding...");
            }

            passedFilter(omg);
            ret.add(omg);
          } else {
            if (DEBUG) {
              Debug.output("   --- OMGraphic fails filter, hiding...");
            }

            failedFilter(omg);
          }
        }
      }
    }

    return ret;
  }
  protected final void compute() {

    ArrayList<Double> xcoord = new ArrayList<Double>();
    ArrayList<Double> ycoord = new ArrayList<Double>();
    double[] coords = new double[6];
    double[] oldCoords = new double[6];

    // Convert input polygons to Area objects
    Area a1 = getArea(inPoly0.getPoints());
    Area a2 = getArea(inPoly1.getPoints());

    // test for empty intersection
    Area testArea = getArea(inPoly0.getPoints());
    testArea.intersect(a2);
    if (testArea.isEmpty()) {
      poly.setUndefined();
    }
    // if intersection is non-empty perform operation
    else {
      switch (operationType) {
        case TYPE_INTERSECTION:
          a1.intersect(a2);
          break;
        case TYPE_UNION:
          a1.add(a2);
          break;
        case TYPE_DIFFERENCE:
          a1.subtract(a2);
          break;
      }

      // Iterate through the path of the result
      // and recover the polygon vertices.

      PathIterator it = a1.getPathIterator(null);

      int type = it.currentSegment(coords);
      it.next();
      oldCoords = coords.clone();
      double epsilon = 1E-10;

      while (!it.isDone()) {
        type = it.currentSegment(coords);
        if (type == PathIterator.SEG_CLOSE) {
          break;
        }
        // Sometimes the Path iterator gives two almost identical points and
        // we only want one of them.
        // TODO: Why does this happen???
        if ((double) Math.abs(oldCoords[0] - coords[0]) > epsilon
            || (double) Math.abs(oldCoords[1] - coords[1]) > epsilon) {
          xcoord.add(coords[0]);
          ycoord.add(coords[1]);
        }
        oldCoords = coords.clone();

        it.next();
      }
    }

    // Update the points array to the correct size
    int n = xcoord.size();
    // System.out.println("number of points: " + n);
    int oldPointNumber = points.length;
    if (n != oldPointNumber) {
      updatePointsArray(n);
      poly.setPoints(points);
      setOutput();
    }

    // Set the points to the new polygon vertices
    for (int k = 0; k < n; k++) {
      points[k].setCoords(xcoord.get(k), ycoord.get(k), 1);
      // System.out.println("vertices: " + xcoord.get(k) + " , " + ycoord.get(k));

    }

    // Compute area of poly (this will also set our poly geo to be defined)
    poly.calcArea();

    // update new points and segments
    if (n != oldPointNumber) {
      updateSegmentsAndPointsLabels(oldPointNumber);
    }
  }
Example #15
0
 public static boolean intersects(Shape shape1, Shape shape2) {
   Area a1 = new Area(shape1);
   Area a2 = new Area(shape2);
   a1.intersect(a2);
   return !a1.isEmpty();
 }
  /**
   * Paints the project onto the canvas and returns the list of components that failed to draw.
   *
   * @param g2d
   * @param project
   * @param drawOptions
   * @param filter
   * @param selectionRect
   * @param selectedComponents
   * @param lockedComponents
   * @param groupedComponents
   * @param controlPointSlot
   * @param componentSlot
   * @param dragInProgress
   * @return
   */
  public List<IDIYComponent<?>> drawProject(
      Graphics2D g2d,
      Project project,
      Set<DrawOption> drawOptions,
      IComponentFiler filter,
      Rectangle selectionRect,
      List<IDIYComponent<?>> selectedComponents,
      Set<IDIYComponent<?>> lockedComponents,
      Set<IDIYComponent<?>> groupedComponents,
      List<Point> controlPointSlot,
      List<IDIYComponent<?>> componentSlot,
      boolean dragInProgress) {
    failedComponents.clear();
    if (project == null) {
      return failedComponents;
    }
    G2DWrapper g2dWrapper = new G2DWrapper(g2d);

    if (drawOptions.contains(DrawOption.ANTIALIASING)) {
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g2d.setRenderingHint(
          RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    } else {
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
      g2d.setRenderingHint(
          RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
    }
    if (ConfigurationManager.getInstance().readBoolean(IPlugInPort.HI_QUALITY_RENDER_KEY, false)) {
      g2d.setRenderingHint(
          RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
      g2d.setRenderingHint(
          RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
      g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
      g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
      g2d.setRenderingHint(
          RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
      // g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
      // RenderingHints.VALUE_STROKE_PURE);
    } else {
      g2d.setRenderingHint(
          RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
      g2d.setRenderingHint(
          RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);
      g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
      g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
      g2d.setRenderingHint(
          RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
    }

    double zoom = 1d;
    if (drawOptions.contains(DrawOption.ZOOM)) {
      zoom = zoomLevel;
    } else {
      zoom = 1 / Constants.PIXEL_SIZE;
    }

    // AffineTransform initialTx = g2d.getTransform();
    Dimension d = getCanvasDimensions(project, zoom, true);

    g2dWrapper.setColor(theme.getBgColor());
    g2dWrapper.fillRect(0, 0, d.width, d.height);
    g2d.clip(new Rectangle(new Point(0, 0), d));

    GridType gridType = GridType.LINES;
    if (drawOptions.contains(DrawOption.GRID) && gridType != GridType.NONE) {
      double zoomStep = project.getGridSpacing().convertToPixels() * zoom;
      if (gridType == GridType.CROSSHAIR) {
        g2d.setStroke(
            new BasicStroke(
                1f,
                BasicStroke.CAP_BUTT,
                BasicStroke.JOIN_MITER,
                10f,
                new float[] {(float) zoomStep / 2, (float) zoomStep / 2},
                (float) zoomStep / 4));
      } else if (gridType == GridType.DOT) {
        g2d.setStroke(
            new BasicStroke(
                1f,
                BasicStroke.CAP_BUTT,
                BasicStroke.JOIN_MITER,
                10f,
                new float[] {1f, (float) zoomStep - 1},
                0f));
      }

      g2dWrapper.setColor(theme.getGridColor());
      for (double i = zoomStep; i < d.width; i += zoomStep) {
        g2dWrapper.drawLine((int) i, 0, (int) i, d.height - 1);
      }
      for (double j = zoomStep; j < d.height; j += zoomStep) {
        g2dWrapper.drawLine(0, (int) j, d.width - 1, (int) j);
      }
    }

    if (Math.abs(1.0 - zoom) > 1e-4) {
      g2dWrapper.scale(zoom, zoom);
    }

    // Composite mainComposite = g2d.getComposite();
    // Composite alphaComposite =
    // AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);

    // g2dWrapper.resetTx();

    // componentAreaMap.clear();
    for (IDIYComponent<?> component : project.getComponents()) {
      // Do not draw the component if it's filtered out.
      if (filter != null && !filter.testComponent(component)) {
        continue;
      }
      ComponentState state = ComponentState.NORMAL;
      if (drawOptions.contains(DrawOption.SELECTION) && selectedComponents.contains(component)) {
        if (dragInProgress) {
          state = ComponentState.DRAGGING;
        } else {
          state = ComponentState.SELECTED;
        }
      }
      // Do not track the area if component is not invalidated and was
      // drawn in the same state.
      boolean trackArea = lastDrawnStateMap.get(component) != state;

      synchronized (g2d) {
        g2dWrapper.startedDrawingComponent();
        if (!trackArea) {
          g2dWrapper.stopTracking();
        }
        // Draw locked components in a new composite.
        if (lockedComponents.contains(component)) {
          g2d.setComposite(lockedComposite);
        }
        // Draw the component through the g2dWrapper.
        try {
          component.draw(
              g2dWrapper,
              state,
              drawOptions.contains(DrawOption.OUTLINE_MODE),
              project,
              g2dWrapper);
        } catch (Exception e) {
          LOG.error("Error drawing " + component.getName(), e);
          failedComponents.add(component);
        }
        Area area = g2dWrapper.finishedDrawingComponent();
        if (trackArea && area != null && !area.isEmpty()) {
          componentAreaMap.put(component, area);
          lastDrawnStateMap.put(component, state);
        }
      }
    }

    // Draw control points.
    if (drawOptions.contains(DrawOption.CONTROL_POINTS)) {
      // Draw unselected points first to make sure they are below.
      if (dragInProgress || drawOptions.contains(DrawOption.OUTLINE_MODE)) {
        for (IDIYComponent<?> component : project.getComponents()) {
          for (int i = 0; i < component.getControlPointCount(); i++) {
            VisibilityPolicy visibilityPolicy = component.getControlPointVisibilityPolicy(i);
            if ((groupedComponents.contains(component)
                    && (visibilityPolicy == VisibilityPolicy.ALWAYS
                        || (selectedComponents.contains(component)
                            && visibilityPolicy == VisibilityPolicy.WHEN_SELECTED))
                || (!groupedComponents.contains(component)
                    && !selectedComponents.contains(component)
                    && component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS))) {
              g2dWrapper.setColor(CONTROL_POINT_COLOR);
              Point controlPoint = component.getControlPoint(i);
              int pointSize = CONTROL_POINT_SIZE - 2;
              g2dWrapper.fillOval(
                  controlPoint.x - pointSize / 2,
                  controlPoint.y - pointSize / 2,
                  pointSize,
                  pointSize);
            }
          }
        }
      }
      // Then draw the selected ones.
      for (IDIYComponent<?> component : selectedComponents) {
        for (int i = 0; i < component.getControlPointCount(); i++) {
          if (!groupedComponents.contains(component)
              && (component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.WHEN_SELECTED
                  || component.getControlPointVisibilityPolicy(i) == VisibilityPolicy.ALWAYS)) {

            Point controlPoint = component.getControlPoint(i);
            int pointSize = CONTROL_POINT_SIZE;

            g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker());
            g2dWrapper.fillOval(
                controlPoint.x - pointSize / 2,
                controlPoint.y - pointSize / 2,
                pointSize,
                pointSize);
            g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR);
            g2dWrapper.fillOval(
                controlPoint.x - CONTROL_POINT_SIZE / 2 + 1,
                controlPoint.y - CONTROL_POINT_SIZE / 2 + 1,
                CONTROL_POINT_SIZE - 2,
                CONTROL_POINT_SIZE - 2);
          }
        }
      }
    }

    // Draw component slot in a separate composite.
    if (componentSlot != null) {
      g2dWrapper.startedDrawingComponent();
      g2dWrapper.setComposite(slotComposite);
      for (IDIYComponent<?> component : componentSlot) {
        try {

          component.draw(
              g2dWrapper,
              ComponentState.NORMAL,
              drawOptions.contains(DrawOption.OUTLINE_MODE),
              project,
              g2dWrapper);

        } catch (Exception e) {
          LOG.error("Error drawing " + component.getName(), e);
          failedComponents.add(component);
        }
      }
      g2dWrapper.finishedDrawingComponent();
    }

    // Draw control points of the component in the slot.
    if (controlPointSlot != null) {
      for (Point point : controlPointSlot) {
        if (point != null) {
          g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR.darker());
          g2dWrapper.fillOval(
              point.x - CONTROL_POINT_SIZE / 2,
              point.y - CONTROL_POINT_SIZE / 2,
              CONTROL_POINT_SIZE,
              CONTROL_POINT_SIZE);
          g2dWrapper.setColor(SELECTED_CONTROL_POINT_COLOR);
          g2dWrapper.fillOval(
              point.x - CONTROL_POINT_SIZE / 2 + 1,
              point.y - CONTROL_POINT_SIZE / 2 + 1,
              CONTROL_POINT_SIZE - 2,
              CONTROL_POINT_SIZE - 2);
        }
      }
    }

    // Go back to the original transformation and zoom in to draw the
    // selection rectangle and other similar elements.
    // g2d.setTransform(initialTx);
    // if ((drawOptions.contains(DrawOption.ZOOM)) && (Math.abs(1.0 -
    // zoomLevel) > 1e-4)) {
    // g2d.scale(zoomLevel, zoomLevel);
    // }

    // At the end draw selection rectangle if needed.
    if (drawOptions.contains(DrawOption.SELECTION) && (selectionRect != null)) {
      g2d.setColor(Color.white);
      g2d.draw(selectionRect);
      g2d.setColor(Color.black);
      g2d.setStroke(Constants.DASHED_STROKE);
      g2d.draw(selectionRect);
    }

    // Draw component area for test
    if (debugComponentAreas) {
      g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
      g2d.setColor(Color.red);
      for (Area area : componentAreaMap.values()) {
        g2d.draw(area);
      }
    }

    return failedComponents;
  }