< prev index next >

modules/graphics/src/main/java/javafx/scene/shape/Cylinder.java

Print this page




  49  * A {@code Cylinder} is a 3D geometry primitive created with a given radius and height.
  50  * It is centered at the origin.
  51  *
  52  * @since JavaFX 8.0
  53  */
  54 public class Cylinder extends Shape3D {
  55     static {
  56          // This is used by classes in different packages to get access to
  57          // private and package private methods.
  58         CylinderHelper.setCylinderAccessor(new CylinderHelper.CylinderAccessor() {
  59             @Override
  60             public NGNode doCreatePeer(Node node) {
  61                 return ((Cylinder) node).doCreatePeer();
  62             }
  63 
  64             @Override
  65             public void doUpdatePeer(Node node) {
  66                 ((Cylinder) node).doUpdatePeer();
  67             }
  68 
















  69         });
  70     }
  71     static final int DEFAULT_DIVISIONS = 64;
  72     static final double DEFAULT_RADIUS = 1;
  73     static final double DEFAULT_HEIGHT = 2;
  74 
  75     private int divisions = DEFAULT_DIVISIONS;
  76     private TriangleMesh mesh;
  77 
  78     {
  79         // To initialize the class helper at the begining each constructor of this class
  80         CylinderHelper.initHelper(this);
  81     }
  82     /**
  83      * Creates a new instance of {@code Cylinder} of radius of 1.0 and height of 2.0.
  84      * Resolution defaults to 15 divisions along X and Z axis.
  85      */
  86     public Cylinder() {
  87         this(DEFAULT_RADIUS, DEFAULT_HEIGHT, DEFAULT_DIVISIONS);
  88     }


 121      * @defaultValue 2.0
 122      */
 123     private DoubleProperty height;
 124 
 125     public final void setHeight(double value) {
 126         heightProperty().set(value);
 127     }
 128 
 129     public final double getHeight() {
 130         return height == null ? 2 : height.get();
 131     }
 132 
 133     public final DoubleProperty heightProperty() {
 134         if (height == null) {
 135             height = new SimpleDoubleProperty(Cylinder.this, "height", DEFAULT_HEIGHT) {
 136                 @Override
 137                 public void invalidated() {
 138                     NodeHelper.markDirty(Cylinder.this, DirtyBits.MESH_GEOM);
 139                     manager.invalidateCylinderMesh(key);
 140                     key = 0;
 141                     impl_geomChanged();
 142                 }
 143             };
 144         }
 145         return height;
 146     }
 147 
 148     /**
 149      * Defines the radius in the Z plane of the Cylinder.
 150      *
 151      * @defaultValue 1.0
 152      */
 153     private DoubleProperty radius;
 154 
 155     public final void setRadius(double value) {
 156         radiusProperty().set(value);
 157     }
 158 
 159     public final double getRadius() {
 160         return radius == null ? 1 : radius.get();
 161     }
 162 
 163     public final DoubleProperty radiusProperty() {
 164         if (radius == null) {
 165             radius = new SimpleDoubleProperty(Cylinder.this, "radius", DEFAULT_RADIUS) {
 166                 @Override
 167                 public void invalidated() {
 168                     NodeHelper.markDirty(Cylinder.this, DirtyBits.MESH_GEOM);
 169                     manager.invalidateCylinderMesh(key);
 170                     key = 0;
 171                     impl_geomChanged();
 172                 }
 173             };
 174         }
 175         return radius;
 176     }
 177 
 178     /**
 179      * Retrieves the divisions attribute use to generate this cylinder.
 180      *
 181      * @return the divisions attribute.
 182      */
 183     public int getDivisions() {
 184         return divisions;
 185     }
 186 
 187     /*
 188      * Note: This method MUST only be called via its accessor method.
 189      */
 190     private void doUpdatePeer() {
 191         if (NodeHelper.isDirty(this, DirtyBits.MESH_GEOM)) {


 195             if (h < 0 || r < 0) {
 196                 peer.updateMesh(null);
 197             } else {
 198                 if (key == 0) {
 199                     key = generateKey(h, r, divisions);
 200                 }
 201                 mesh = manager.getCylinderMesh(h, r, divisions, key);
 202                 mesh.updatePG();
 203                 peer.updateMesh(mesh.getPGTriangleMesh());
 204             }
 205         }
 206     }
 207 
 208     /*
 209      * Note: This method MUST only be called via its accessor method.
 210      */
 211     private NGNode doCreatePeer() {
 212         return new NGCylinder();
 213     }
 214 
 215     /**
 216      * @treatAsPrivate implementation detail
 217      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 218      */
 219     @Deprecated
 220     @Override
 221     public BaseBounds impl_computeGeomBounds(BaseBounds bounds, BaseTransform tx) {
 222         final float h = (float) getHeight();
 223         final float r = (float) getRadius();
 224 
 225         if (r < 0 || h < 0) {
 226             return bounds.makeEmpty();
 227         }
 228 
 229         final float hh = h * 0.5f;
 230 
 231         bounds = bounds.deriveWithNewBounds(-r, -hh, -r, r, hh, r);
 232         bounds = tx.transform(bounds, bounds);
 233         return bounds;
 234     }
 235 
 236     /**
 237      * @treatAsPrivate implementation detail
 238      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 239      */
 240     @Deprecated
 241     @Override
 242     protected boolean impl_computeContains(double localX, double localY) {
 243         double w = getRadius();
 244         double hh = getHeight()*.5f;
 245         return -w <= localX && localX <= w &&
 246                 -hh <= localY && localY <= hh;
 247     }
 248 
 249     /**
 250      * @treatAsPrivate implementation detail
 251      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 252      */
 253     @Deprecated
 254     @Override
 255     protected boolean impl_computeIntersects(PickRay pickRay, PickResultChooser pickResult) {
 256 
 257         final boolean exactPicking = divisions < DEFAULT_DIVISIONS && mesh != null;
 258 
 259         final double r = getRadius();
 260         final Vec3d dir = pickRay.getDirectionNoClone();
 261         final double dirX = dir.x;
 262         final double dirY = dir.y;
 263         final double dirZ = dir.z;
 264         final Vec3d origin = pickRay.getOriginNoClone();
 265         final double originX = origin.x;
 266         final double originY = origin.y;
 267         final double originZ = origin.z;
 268         final double h = getHeight();
 269         final double halfHeight = h / 2.0;
 270         final CullFace cullFace = getCullFace();
 271 
 272         // Check the open cylinder first
 273 
 274         // Coeficients of a quadratic equation desribing intersection with an infinite cylinder
 275         final double a = dirX * dirX + dirZ * dirZ;




  49  * A {@code Cylinder} is a 3D geometry primitive created with a given radius and height.
  50  * It is centered at the origin.
  51  *
  52  * @since JavaFX 8.0
  53  */
  54 public class Cylinder extends Shape3D {
  55     static {
  56          // This is used by classes in different packages to get access to
  57          // private and package private methods.
  58         CylinderHelper.setCylinderAccessor(new CylinderHelper.CylinderAccessor() {
  59             @Override
  60             public NGNode doCreatePeer(Node node) {
  61                 return ((Cylinder) node).doCreatePeer();
  62             }
  63 
  64             @Override
  65             public void doUpdatePeer(Node node) {
  66                 ((Cylinder) node).doUpdatePeer();
  67             }
  68 
  69             @Override
  70             public BaseBounds doComputeGeomBounds(Node node,
  71             BaseBounds bounds, BaseTransform tx) {
  72                 return ((Cylinder) node).doComputeGeomBounds(bounds, tx);
  73             }
  74 
  75             @Override
  76             public boolean doComputeContains(Node node, double localX, double localY) {
  77                 return ((Cylinder) node).doComputeContains(localX, localY);
  78             }
  79 
  80             @Override
  81             public boolean doComputeIntersects(Node node, PickRay pickRay,
  82             PickResultChooser pickResult) {
  83                 return ((Cylinder) node).doComputeIntersects(pickRay, pickResult);
  84             }
  85         });
  86     }
  87     static final int DEFAULT_DIVISIONS = 64;
  88     static final double DEFAULT_RADIUS = 1;
  89     static final double DEFAULT_HEIGHT = 2;
  90 
  91     private int divisions = DEFAULT_DIVISIONS;
  92     private TriangleMesh mesh;
  93 
  94     {
  95         // To initialize the class helper at the begining each constructor of this class
  96         CylinderHelper.initHelper(this);
  97     }
  98     /**
  99      * Creates a new instance of {@code Cylinder} of radius of 1.0 and height of 2.0.
 100      * Resolution defaults to 15 divisions along X and Z axis.
 101      */
 102     public Cylinder() {
 103         this(DEFAULT_RADIUS, DEFAULT_HEIGHT, DEFAULT_DIVISIONS);
 104     }


 137      * @defaultValue 2.0
 138      */
 139     private DoubleProperty height;
 140 
 141     public final void setHeight(double value) {
 142         heightProperty().set(value);
 143     }
 144 
 145     public final double getHeight() {
 146         return height == null ? 2 : height.get();
 147     }
 148 
 149     public final DoubleProperty heightProperty() {
 150         if (height == null) {
 151             height = new SimpleDoubleProperty(Cylinder.this, "height", DEFAULT_HEIGHT) {
 152                 @Override
 153                 public void invalidated() {
 154                     NodeHelper.markDirty(Cylinder.this, DirtyBits.MESH_GEOM);
 155                     manager.invalidateCylinderMesh(key);
 156                     key = 0;
 157                     NodeHelper.geomChanged(Cylinder.this);
 158                 }
 159             };
 160         }
 161         return height;
 162     }
 163 
 164     /**
 165      * Defines the radius in the Z plane of the Cylinder.
 166      *
 167      * @defaultValue 1.0
 168      */
 169     private DoubleProperty radius;
 170 
 171     public final void setRadius(double value) {
 172         radiusProperty().set(value);
 173     }
 174 
 175     public final double getRadius() {
 176         return radius == null ? 1 : radius.get();
 177     }
 178 
 179     public final DoubleProperty radiusProperty() {
 180         if (radius == null) {
 181             radius = new SimpleDoubleProperty(Cylinder.this, "radius", DEFAULT_RADIUS) {
 182                 @Override
 183                 public void invalidated() {
 184                     NodeHelper.markDirty(Cylinder.this, DirtyBits.MESH_GEOM);
 185                     manager.invalidateCylinderMesh(key);
 186                     key = 0;
 187                     NodeHelper.geomChanged(Cylinder.this);
 188                 }
 189             };
 190         }
 191         return radius;
 192     }
 193 
 194     /**
 195      * Retrieves the divisions attribute use to generate this cylinder.
 196      *
 197      * @return the divisions attribute.
 198      */
 199     public int getDivisions() {
 200         return divisions;
 201     }
 202 
 203     /*
 204      * Note: This method MUST only be called via its accessor method.
 205      */
 206     private void doUpdatePeer() {
 207         if (NodeHelper.isDirty(this, DirtyBits.MESH_GEOM)) {


 211             if (h < 0 || r < 0) {
 212                 peer.updateMesh(null);
 213             } else {
 214                 if (key == 0) {
 215                     key = generateKey(h, r, divisions);
 216                 }
 217                 mesh = manager.getCylinderMesh(h, r, divisions, key);
 218                 mesh.updatePG();
 219                 peer.updateMesh(mesh.getPGTriangleMesh());
 220             }
 221         }
 222     }
 223 
 224     /*
 225      * Note: This method MUST only be called via its accessor method.
 226      */
 227     private NGNode doCreatePeer() {
 228         return new NGCylinder();
 229     }
 230 
 231     /*
 232      * Note: This method MUST only be called via its accessor method.

 233      */
 234     private BaseBounds doComputeGeomBounds(BaseBounds bounds, BaseTransform tx) {


 235         final float h = (float) getHeight();
 236         final float r = (float) getRadius();
 237 
 238         if (r < 0 || h < 0) {
 239             return bounds.makeEmpty();
 240         }
 241 
 242         final float hh = h * 0.5f;
 243 
 244         bounds = bounds.deriveWithNewBounds(-r, -hh, -r, r, hh, r);
 245         bounds = tx.transform(bounds, bounds);
 246         return bounds;
 247     }
 248 
 249     /*
 250      * Note: This method MUST only be called via its accessor method.

 251      */
 252     private boolean doComputeContains(double localX, double localY) {


 253         double w = getRadius();
 254         double hh = getHeight()*.5f;
 255         return -w <= localX && localX <= w &&
 256                 -hh <= localY && localY <= hh;
 257     }
 258 
 259     /*
 260      * Note: This method MUST only be called via its accessor method.

 261      */
 262     private boolean doComputeIntersects(PickRay pickRay, PickResultChooser pickResult) {


 263 
 264         final boolean exactPicking = divisions < DEFAULT_DIVISIONS && mesh != null;
 265 
 266         final double r = getRadius();
 267         final Vec3d dir = pickRay.getDirectionNoClone();
 268         final double dirX = dir.x;
 269         final double dirY = dir.y;
 270         final double dirZ = dir.z;
 271         final Vec3d origin = pickRay.getOriginNoClone();
 272         final double originX = origin.x;
 273         final double originY = origin.y;
 274         final double originZ = origin.z;
 275         final double h = getHeight();
 276         final double halfHeight = h / 2.0;
 277         final CullFace cullFace = getCullFace();
 278 
 279         // Check the open cylinder first
 280 
 281         // Coeficients of a quadratic equation desribing intersection with an infinite cylinder
 282         final double a = dirX * dirX + dirZ * dirZ;


< prev index next >