/*
* $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.afp;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Path2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import javax.imageio.ImageIO;
import org.junit.After;
import org.junit.Before;
import org.junit.ComparisonFailure;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.arakhne.afc.math.AbstractMathTestCase;
import org.arakhne.afc.math.geometry.PathElementType;
import org.arakhne.afc.math.geometry.PathWindingRule;
import org.arakhne.afc.math.geometry.coordinatesystem.CoordinateSystem3DTestRule;
import org.arakhne.afc.math.geometry.d3.Point3D;
import org.arakhne.afc.math.geometry.d3.Vector3D;
@SuppressWarnings("all")
public abstract class AbstractShape3afpTest<T extends Shape3afp<?, ?, ?, ?, ?, ?>,
B extends RectangularPrism3afp<?, ?, ?, ?, ?, B>> extends AbstractMathTestCase {
@Rule
public CoordinateSystem3DTestRule csTestRule = new CoordinateSystem3DTestRule();
/** Is the rectangular shape to test.
*/
protected T shape;
/** Shape factory.
*/
protected TestShapeFactory3afp<? extends Point3D, ? extends Vector3D, B> factory;
/**
* @throws Exception
*/
@Before
public void setUp() throws Exception {
this.factory = createFactory();
this.shape = createShape();
}
protected abstract TestShapeFactory3afp<? extends Point3D, ? extends Vector3D, B> createFactory();
/** Create the shape to test.
*
* @return the shape to test.
*/
protected abstract T createShape();
public final Segment3afp<?, ?, ?, ?, ?, B> createSegment(double x1, double y1, double z1, double x2, double y2, double z2) {
return this.factory.createSegment(x1, y1, z1, x2, y2, z2);
}
public final B createRectangularPrism(double x, double y, double z, double width, double height, double depth) {
return this.factory.createRectangularPrism(x, y, z, width, height, depth);
}
public final Sphere3afp<?, ?, ?, ?, ?, B> createSphere(double x, double y, double z, double radius) {
return this.factory.createSphere(x, y, z, radius);
}
public final MultiShape3afp<?, ?, ?, ?, ?, ?, B> createMultiShape() {
return this.factory.createMultiShape();
}
public final Point3D createPoint(double x, double y, double z) {
return this.factory.createPoint(x, y, z);
}
public final Vector3D createVector(double x, double y, double z) {
return this.factory.createVector(x, y, z);
}
public final Path3afp<?, ?, ?, ?, ?, B> createPath() {
return this.factory.createPath(null);
}
public final Path3afp<?, ?, ?, ?, ?, B> createPath(PathWindingRule rule) {
return this.factory.createPath(rule);
}
public final Path3afp<?, ?, ?, ?, ?, B> createPolyline(double... coordinates) {
Path3afp<?, ?, ?, ?, ?, B> path = createPath();
path.moveTo(coordinates[0], coordinates[1], coordinates[2]);
for (int i = 3; i < coordinates.length; i += 3) {
path.lineTo(coordinates[i], coordinates[i + 1], coordinates[i + 2]);
}
return path;
}
/**
* @throws Exception
*/
@After
public void tearDown() throws Exception {
this.shape = null;
}
/** Assert is the given path iterator has a first element with the
* given information.
*
* @param pi
* @param type
* @param coords
*/
protected void assertElement(PathIterator3afp<?> pi, PathElementType type, double... coords) {
if (!pi.hasNext()) {
fail("expected path element but the iterator is empty"); //$NON-NLS-1$
}
PathElement3afp pe = pi.next();
if (!type.equals(pe.getType())) {
throw new ComparisonFailure("not same element type.", type.name(), pe.getType().name()); //$NON-NLS-1$
}
double[] c = new double[coords.length];
pe.toArray(c);
if (!isEpsilonEquals(c, coords)) {
throw new ComparisonFailure("not same coordinates.", //$NON-NLS-1$
Arrays.toString(coords),
Arrays.toString(c));
}
}
/**
* Replies if two arrays have the same values at epsilon.
*
* @param a
* @param b
* @return <code>true</code> if the two arrays are equal, otherwise
* <code>false</code>.
*/
public boolean isEpsilonEquals(float[] a, float[] b) {
if (a==b) return true;
if (a==null && b!=null) return false;
if (a!=null && b==null) return false;
assert(a!=null && b!=null);
if (a.length!=b.length) return false;
for(int i=0; i<a.length; ++i) {
if (!isEpsilonEquals(a[i], b[i])) return false;
}
return true;
}
/**
* Replies if two arrays have the same values at epsilon.
*
* @param a
* @param b
* @return <code>true</code> if the two arrays are equal, otherwise
* <code>false</code>.
*/
protected boolean isEquals(int[] a, int[] b) {
if (a==b) return true;
if (a==null && b!=null) return false;
if (a!=null && b==null) return false;
assert(a!=null && b!=null);
if (a.length!=b.length) return false;
for(int i=0; i<a.length; ++i) {
if (a[i]!=b[i]) return false;
}
return true;
}
/** Assert is the given path iterator has no element.
*
* @param pi
*/
protected void assertNoElement(PathIterator3afp<?> pi) {
if (pi.hasNext()) {
fail("expected no path element but the iterator is not empty: " //$NON-NLS-1$
+ pi.next());
}
}
@Test
@Ignore
public abstract void testClone();
@Test
@Ignore
public abstract void equalsObject();
@Test
@Ignore
public abstract void equalsObject_withPathIterator();
@Test
@Ignore
public abstract void equalsToPathIterator();
@Test
@Ignore
public abstract void equalsToShape();
@Test
public abstract void isEmpty();
@Test
public abstract void clear();
@Test
@Ignore
public abstract void containsPoint3D();
@Test
@Ignore
public abstract void getClosestPointTo();
@Test
@Ignore
public abstract void getFarthestPointTo();
@Test
@Ignore
public abstract void getDistance();
@Test
@Ignore
public abstract void getDistanceSquared();
@Test
@Ignore
public abstract void getDistanceL1();
@Test
@Ignore
public abstract void getDistanceLinf();
@Test
@Ignore
public abstract void setIT();
@Test
@Ignore
public abstract void getPathIterator();
@Test
@Ignore
public abstract void getPathIteratorTransform3D();
@Test
@Ignore
public abstract void createTransformedShape();
@Test
@Ignore
public abstract void translateVector3D();
@Test
@Ignore
public abstract void toBoundingBox();
@Test
@Ignore
public abstract void toBoundingBoxB();
@Test
@Ignore
public abstract void containsRectangularPrism3afp();
@Test
@Ignore
public abstract void intersectsRectangularPrism3afp();
@Test
@Ignore
public abstract void intersectsSphere3afp();
@Test
@Ignore
public abstract void intersectsSegment3afp();
@Test
@Ignore
public abstract void intersectsPath3afp();
@Test
@Ignore
public abstract void intersectsPathIterator3afp();
@Test
@Ignore
public abstract void translateDoubleDouble();
@Test
@Ignore
public abstract void containsDoubleDouble();
@Test
public void getGeomFactory() {
assertNotNull(this.shape.getGeomFactory());
}
@Test
@Ignore
public abstract void intersectsShape3D();
@Test
@Ignore
public abstract void operator_addVector3D();
@Test
@Ignore
public abstract void operator_plusVector3D();
@Test
@Ignore
public abstract void operator_removeVector3D();
@Test
@Ignore
public abstract void operator_minusVector3D();
@Test
@Ignore
public abstract void operator_multiplyTransform3D();
@Test
@Ignore
public abstract void operator_andPoint3D();
@Test
@Ignore
public abstract void operator_andShape3D();
@Test
@Ignore
public abstract void operator_upToPoint3D();
/** Generate a bitmap containing the given Shape2D.
*
* @param shape.
* @return the filename
* @throws IOException Input/output exception
*/
public static File generateTestPicture(Shape3afp<?, ?, ?, ?, ?, ?> shape) throws IOException {
File filename = File.createTempFile("testShape", ".png"); //$NON-NLS-1$ //$NON-NLS-2$
RectangularPrism3afp box = shape.toBoundingBox();
PathIterator3afp<?> iterator = shape.getPathIterator();
Path2D path = new Path2D.Double(
iterator.getWindingRule() == PathWindingRule.NON_ZERO ? Path2D.WIND_NON_ZERO : Path2D.WIND_EVEN_ODD);
while (iterator.hasNext()) {
PathElement3afp element = iterator.next();
double tox = (element.getToX() - box.getMinX()) * 2.;
double toy = (box.getMaxY() - (element.getToY() - box.getMinY())) * 2.;
switch (element.getType()) {
case LINE_TO:
path.lineTo(tox, toy);
break;
case MOVE_TO:
path.moveTo(tox, toy);
break;
case CLOSE:
path.closePath();
break;
case CURVE_TO:
path.curveTo(
(element.getCtrlX1() - box.getMinX()) * 2.,
(box.getMaxY() - (element.getCtrlY1() - box.getMinY())) * 2.,
(element.getCtrlX2() - box.getMinX()) * 2.,
(box.getMaxY() - (element.getCtrlY2() - box.getMinY())) * 2.,
tox, toy);
break;
case QUAD_TO:
path.quadTo(
(element.getCtrlX1() - box.getMinX()) * 2.,
(box.getMaxY() - (element.getCtrlY1() - box.getMinY())) * 2.,
tox, toy);
break;
case ARC_TO:
throw new IllegalArgumentException();
default:
}
}
BufferedImage image = new BufferedImage(
(int) Math.floor(box.getWidth() * 2.) + 1,
(int) Math.floor(box.getHeight() * 2.) + 1,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.setColor(Color.BLACK);
g2d.draw(path);
ImageIO.write(image, "png", filename); //$NON-NLS-1$
return filename;
}
}