/*
* $Id$
* This file is a part of the Arakhne Foundation Classes, http://www.arakhne.org/afc
*
* Copyright (c) 2000-2012 Stephane GALLAND.
* Copyright (c) 2005-10, Multiagent Team, Laboratoire Systemes et Transports,
* Universite de Technologie de Belfort-Montbeliard.
* Copyright (c) 2013-2016 The original authors, and other authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.arakhne.afc.math.geometry.d3.ifx;
import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyIntegerWrapper;
import javafx.beans.property.SimpleObjectProperty;
import org.eclipse.xtext.xbase.lib.Pure;
import org.arakhne.afc.math.geometry.MathFXAttributeNames;
import org.arakhne.afc.math.geometry.d3.Point3D;
import org.arakhne.afc.math.geometry.d3.ai.RectangularPrism3ai;
import org.arakhne.afc.vmutil.asserts.AssertMessages;
/** A rectangular prism with 3 integer FX properties.
*
* @author $Author: sgalland$
* @author $Author: tpiotrow$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
* @since 13.0
*/
public class RectangularPrism3ifx extends AbstractShape3ifx<RectangularPrism3ifx> implements
RectangularPrism3ai<Shape3ifx<?>, RectangularPrism3ifx, PathElement3ifx, Point3ifx, Vector3ifx, RectangularPrism3ifx> {
private static final long serialVersionUID = -8092385681401129843L;
private Point3ifx min = new Point3ifx();
private Point3ifx max = new Point3ifx();
/** width property.
*/
private ReadOnlyIntegerWrapper width;
/** height property.
*/
private ReadOnlyIntegerWrapper height;
/** depth property.
*/
private ReadOnlyIntegerWrapper depth;
/** Construct an empty rectangle.
*/
public RectangularPrism3ifx() {
addListeners();
}
/** Construct a rectangular prism with the given minimum and maximum corners.
* @param min is the min corner of the rectangle.
* @param max is the max corner of the rectangle.
*/
public RectangularPrism3ifx(Point3D<?, ?> min, Point3D<?, ?> max) {
assert min != null : AssertMessages.notNullParameter(0);
assert max != null : AssertMessages.notNullParameter(1);
setFromCorners(min.ix(), min.iy(), min.iz(), max.ix(), max.iy(), max.iz());
}
/** Construct a rectangular prism by setting the given minimum and maximum corners.
* @param min is the min corner of the rectangle.
* @param max is the max corner of the rectangle.
*/
public RectangularPrism3ifx(Point3ifx min, Point3ifx max) {
assert min != null : AssertMessages.notNullParameter(0);
assert max != null : AssertMessages.notNullParameter(1);
this.min = min;
this.max = max;
}
/** Construct a rectangle with the given minimum corner and sizes.
* @param x x coordinate of the minimum corner.
* @param y y coordinate of the minimum corner.
* @param z z coordinate of the minimum corner.
* @param width width of the rectangle.
* @param height height of the rectangle.
* @param depth depth of the rectangle.
*/
@SuppressWarnings("checkstyle:magicnumber")
public RectangularPrism3ifx(int x, int y, int z, int width, int height, int depth) {
assert width >= 0 : AssertMessages.positiveOrZeroParameter(3);
assert height >= 0 : AssertMessages.positiveOrZeroParameter(4);
assert depth >= 0 : AssertMessages.positiveOrZeroParameter(5);
setFromCorners(x, y, z, x + width, y + height, z + depth);
}
/** Constructor by copy.
* @param rectangle the rectangle to copy.
*/
public RectangularPrism3ifx(RectangularPrism3ai<?, ?, ?, ?, ?, ?> rectangle) {
assert rectangle != null : AssertMessages.notNullParameter();
setFromCorners(rectangle.getMinX(), rectangle.getMinY(), rectangle.getMinZ(), rectangle.getMaxX(), rectangle.getMaxY(),
rectangle.getMaxZ());
}
/** Constructor by setting.
* @param rectangle the rectangle to set.
*/
public RectangularPrism3ifx(RectangularPrism3ifx rectangle) {
assert rectangle != null : AssertMessages.notNullParameter();
this.min = rectangle.min;
this.max = rectangle.max;
}
@Override
public RectangularPrism3ifx clone() {
final RectangularPrism3ifx clone = super.clone();
if (clone.min != null) {
clone.min = null;
clone.min = this.min.clone();
}
if (clone.max != null) {
clone.max = null;
clone.max = this.max.clone();
}
return clone;
}
@Override
public void setFromCorners(int x1, int y1, int z1, int x2, int y2, int z2) {
if (x1 <= x2) {
minXProperty().set(x1);
maxXProperty().set(x2);
} else {
minXProperty().set(x2);
maxXProperty().set(x1);
}
if (y1 <= y2) {
minYProperty().set(y1);
maxYProperty().set(y2);
} else {
minYProperty().set(y2);
maxYProperty().set(y1);
}
if (z1 <= z2) {
minZProperty().set(z1);
maxZProperty().set(z2);
} else {
minZProperty().set(z2);
maxZProperty().set(z1);
}
addListeners();
}
/**
* Add a listener to the point properties to observe correct min-max behavior.
*/
private void addListeners() {
this.min.xProperty().addListener((observable, oldValue, nValue) -> {
final int currentMin = nValue.intValue();
final int currentMax = getMaxX();
if (currentMax < currentMin) {
// min-max constrain is broken
maxXProperty().set(currentMin);
}
});
this.min.yProperty().addListener((observable, oValue, nValue) -> {
final int currentMin = nValue.intValue();
final int currentMax = getMaxY();
if (currentMax < currentMin) {
// min-max constrain is broken
maxYProperty().set(currentMin);
}
});
this.min.zProperty().addListener((observable, oValue, nValue) -> {
final int currentMin = nValue.intValue();
final int currentMax = getMaxZ();
if (currentMax < currentMin) {
// min-max constrain is broken
maxZProperty().set(currentMin);
}
});
this.max.xProperty().addListener((observable, oValue, nValue) -> {
final int currentMax = nValue.intValue();
final int currentMin = getMinX();
if (currentMax < currentMin) {
// min-max constrain is broken
minXProperty().set(currentMax);
}
});
this.max.yProperty().addListener((observable, oValue, nValue) -> {
final int currentMax = nValue.intValue();
final int currentMin = getMinY();
if (currentMax < currentMin) {
// min-max constrain is broken
minYProperty().set(currentMax);
}
});
this.max.zProperty().addListener((observable, oValue, nValue) -> {
final int currentMax = nValue.intValue();
final int currentMin = getMinZ();
if (currentMax < currentMin) {
// min-max constrain is broken
minZProperty().set(currentMax);
}
});
}
@Pure
@Override
public int getMinX() {
return this.min.ix();
}
@Override
public void setMinX(int x) {
minXProperty().set(x);
}
/** Replies the property that is the minimum x coordinate of the box.
*
* @return the minX property.
*/
@Pure
public IntegerProperty minXProperty() {
return this.min.xProperty();
}
@Pure
@Override
public int getMaxX() {
return this.max.ix();
}
@Override
public void setMaxX(int x) {
maxXProperty().set(x);
}
/** Replies the property that is the maximum x coordinate of the box.
*
* @return the maxX property.
*/
@Pure
public IntegerProperty maxXProperty() {
return this.max.xProperty();
}
@Pure
@Override
public int getMinY() {
return this.min.iy();
}
@Override
public void setMinY(int y) {
minYProperty().set(y);
}
/** Replies the property that is the minimum y coordinate of the box.
*
* @return the minY property.
*/
@Pure
public IntegerProperty minYProperty() {
return this.min.yProperty();
}
@Pure
@Override
public int getMaxY() {
return this.max.iy();
}
@Override
public void setMaxY(int y) {
maxYProperty().set(y);
}
/** Replies the property that is the maximum y coordinate of the box.
*
* @return the maxY property.
*/
@Pure
public IntegerProperty maxYProperty() {
return this.max.yProperty();
}
@Pure
@Override
public int getMinZ() {
return this.min.iz();
}
@Override
public void setMinZ(int z) {
minZProperty().set(z);
}
/** Replies the property that is the minimum z coordinate of the box.
*
* @return the minZ property.
*/
@Pure
public IntegerProperty minZProperty() {
return this.min.zProperty();
}
@Pure
@Override
public int getMaxZ() {
return this.max.iz();
}
@Override
public void setMaxZ(int z) {
maxZProperty().set(z);
}
/** Replies the property that is the maximum z coordinate of the box.
*
* @return the maxZ property.
*/
@Pure
public IntegerProperty maxZProperty() {
return this.max.zProperty();
}
@Pure
@Override
public int hashCode() {
int bits = 1;
bits = 31 * bits + getMinX();
bits = 31 * bits + getMinY();
bits = 31 * bits + getMaxX();
bits = 31 * bits + getMaxY();
return bits ^ (bits >> 31);
}
@Override
public int getWidth() {
return widthProperty().get();
}
/** Replies the property that is the width of the box.
*
* @return the width property.
*/
@Pure
public IntegerProperty widthProperty() {
if (this.width == null) {
this.width = new ReadOnlyIntegerWrapper(this, MathFXAttributeNames.WIDTH);
this.width.bind(Bindings.subtract(maxXProperty(), minXProperty()));
}
return this.width;
}
@Override
public int getHeight() {
return heightProperty().get();
}
/** Replies the property that is the height of the box.
*
* @return the height property.
*/
@Pure
public IntegerProperty heightProperty() {
if (this.height == null) {
this.height = new ReadOnlyIntegerWrapper(this, MathFXAttributeNames.HEIGHT);
this.height.bind(Bindings.subtract(maxYProperty(), minYProperty()));
}
return this.height;
}
@Override
public int getDepth() {
return depthProperty().get();
}
/** Replies the property that is the depth of the box.
*
* @return the depth property.
*/
@Pure
public IntegerProperty depthProperty() {
if (this.depth == null) {
this.depth = new ReadOnlyIntegerWrapper(this, MathFXAttributeNames.DEPTH);
this.depth.bind(Bindings.subtract(maxZProperty(), minZProperty()));
}
return this.depth;
}
@Override
public ObjectProperty<RectangularPrism3ifx> boundingBoxProperty() {
if (this.boundingBox == null) {
this.boundingBox = new SimpleObjectProperty<>(this, MathFXAttributeNames.BOUNDING_BOX);
this.boundingBox.bind(Bindings.createObjectBinding(() ->
toBoundingBox(),
minXProperty(), minYProperty(), widthProperty(), heightProperty()));
}
return this.boundingBox;
}
}