All Downloads are FREE. Search and download functionalities are using the official Maven repository.

us.ihmc.scs2.sessionVisualizer.jfx.yoGraphic.YoPointFX2D Maven / Gradle / Ivy

package us.ihmc.scs2.sessionVisualizer.jfx.yoGraphic;

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Bounds;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Shape;
import javafx.scene.transform.Scale;
import javafx.scene.transform.Translate;
import net.javainthebox.caraibe.svg.SVGContent;
import net.javainthebox.caraibe.svg.SVGLoader;
import us.ihmc.euclid.tuple2D.Point2D;
import us.ihmc.scs2.sessionVisualizer.jfx.managers.ReferenceFrameWrapper;
import us.ihmc.scs2.sessionVisualizer.jfx.yoComposite.Tuple2DProperty;

import java.util.List;

public class YoPointFX2D extends YoGraphicFX2D
{
   private final Group pointNode = new Group();

   private Tuple2DProperty position = new Tuple2DProperty(null, 0.0, 0.0);
   private DoubleProperty size = new SimpleDoubleProperty(0.1);
   private final Translate translate = new Translate();
   private final Scale scale = new Scale();
   private final ObjectProperty fillProperty = new SimpleObjectProperty<>(this, "fillProperty", null);
   private final ObjectProperty strokeProperty = new SimpleObjectProperty<>(this, "strokeProperty", Color.BLACK);
   private final DoubleProperty strokeWidthProperty = new SimpleDoubleProperty(this, "strokeWidthProperty", 0.0);
   private YoGraphicFXResource graphicResource;

   public YoPointFX2D()
   {
      pointNode.getTransforms().addAll(translate, scale);
      pointNode.idProperty().bind(nameProperty());
      pointNode.getProperties().put(YO_GRAPHICFX_ITEM_KEY, this);
      setGraphicResource(YoGraphicFXResourceManager.DEFAULT_POINT2D_GRAPHIC_RESOURCE);
   }

   public YoPointFX2D(ReferenceFrameWrapper worldFrame)
   {
      this();
      position.setReferenceFrame(worldFrame);
   }

   private SVGContent graphic = null;

   public void setGraphicResource(YoGraphicFXResource graphicResource)
   {
      this.graphicResource = graphicResource;
      pointNode.getChildren().clear();

      if (graphicResource == null || graphicResource.getResourceURL() == null)
         return;

      graphic = SVGLoader.load(graphicResource.getResourceURL());

      List shapes = YoGraphicTools.extractShapes(graphic);
      Translate graphicCentering = new Translate();
      Bounds layoutBounds = graphic.getLayoutBounds();
      graphicCentering.setX(-0.5 * (layoutBounds.getMinX() + layoutBounds.getMaxX()));
      graphicCentering.setY(-0.5 * (layoutBounds.getMinY() + layoutBounds.getMaxY()));

      for (Shape shape : shapes)
      {
         shape.getTransforms().add(graphicCentering);
         shape.fillProperty().bind(fillProperty);
         shape.strokeProperty().bind(strokeProperty);
         shape.strokeWidthProperty().bind(strokeWidthProperty);
         shape.idProperty().bind(nameProperty());
      }
   }

   @Override
   public void render()
   {
      // If the SVG is a path, it seems that hiding it by setting the translation to a large number and setting the scale to 0 may result in the following exception:
      // java.lang.IllegalStateException: Trying to remove a cached item that's not in the cache
      // Removing and adding the graphic back to the pointNode group seems to avoid that issue.
      if (position.containsNaN())
      {
         pointNode.getChildren().clear();
         //         translate.setX(Double.NEGATIVE_INFINITY);
         //         translate.setY(Double.NEGATIVE_INFINITY);
         //         scale.setX(0.0);
         //         scale.setY(0.0);
         return;
      }
      else
      {
         if (pointNode.getChildren().isEmpty())
            pointNode.getChildren().add(graphic);
         else if (pointNode.getChildren().get(0) != graphic)
            pointNode.getChildren().set(0, graphic);
      }

      Point2D positionInWorld = position.toPoint2DInWorld();
      translate.setX(positionInWorld.getX());
      translate.setY(positionInWorld.getY());
      scale.setX(YoGraphicFXResourceManager.SVG_SCALE * size.get());
      scale.setY(YoGraphicFXResourceManager.SVG_SCALE * size.get());

      fillProperty.set(fillColor == null ? null : fillColor.get());
      strokeProperty.set(strokeColor == null ? null : strokeColor.get());

      if (strokeWidth == null)
         strokeWidth = YoGraphicFX2D.DEFAULT_STROKE_WIDTH;

      double scale = pointNode.getLocalToSceneTransform().deltaTransform(1.0, 0.0).getX();
      strokeWidthProperty.set(strokeWidth.get() / scale);
   }

   public void setPosition(Tuple2DProperty position)
   {
      this.position = position;
   }

   public void setSize(DoubleProperty size)
   {
      this.size = size;
   }

   public void setSize(double size)
   {
      this.size = new SimpleDoubleProperty(size);
   }

   @Override
   public void clear()
   {
      position = null;
      size = null;
      fillColor = null;
      strokeColor = null;
      strokeWidth = null;
      graphicResource = null;
   }

   @Override
   public YoPointFX2D clone()
   {
      YoPointFX2D clone = new YoPointFX2D();
      clone.setName(getName());
      clone.setPosition(new Tuple2DProperty(position));
      clone.setSize(size);
      clone.setFillColor(fillColor);
      clone.setStrokeColor(strokeColor);
      clone.setStrokeWidth(strokeWidth);
      clone.setGraphicResource(graphicResource);
      return clone;
   }

   public Tuple2DProperty getPosition()
   {
      return position;
   }

   public DoubleProperty getSize()
   {
      return size;
   }

   public YoGraphicFXResource getGraphicResource()
   {
      return graphicResource;
   }

   @Override
   public Node getNode()
   {
      return pointNode;
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy