package cz.fidentis.analyst.mesh.core;

import java.util.List;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/**
 *
 * @author oslejsek
 * @author Dominik Racek
 */
public class MeshTriangleTest {
    
    /*
    protected MeshTriangle getTriangle() {
        MeshTriangle triangle = new MeshTriangle(
                new MeshPointImpl(new Vector3d(1, 0, 0), null, null),
                new MeshPointImpl(new Vector3d(1, 2, 0), null, null),
                new MeshPointImpl(new Vector3d(2, 0, 0), null, null),
                0, 1, 2
        );
        return triangle;
    }
    
    @Test
    public void getClosestPointTest() {
        MeshTriangle tri = new MeshTriangle(
                new MeshPointImpl(new Vector3d(1, 0, 0), null, null),
                new MeshPointImpl(new Vector3d(1, 2, 0), null, null),
                new MeshPointImpl(new Vector3d(2, 0, 0), null, null),
                0, 1, 2
        );
        Assertions.assertEquals(new Vector3d(1, 0, 0), tri.getClosestPoint(new Vector3d(0, 0, 0)));
        Assertions.assertEquals(new Vector3d(1, 1, 0), tri.getClosestPoint(new Vector3d(0, 1, 0)));
        Assertions.assertEquals(new Vector3d(1, 2, 0), tri.getClosestPoint(new Vector3d(0, 3, 0)));
        Assertions.assertEquals(new Vector3d(1, 0, 0), tri.getClosestPoint(new Vector3d(1, 0, -1)));
        Assertions.assertEquals(new Vector3d(1.2, 0.2, 0), tri.getClosestPoint(new Vector3d(1.2, 0.2, -1)));
    }
    */

    private MeshFacet createFacet() {
        MeshFacet facet = new MeshFacetImpl();
        facet.addVertex(new MeshPointImpl(new Point3d(0, 0, 0), null, null));
        facet.addVertex(new MeshPointImpl(new Point3d(1, 0, 0), null, null));
        facet.addVertex(new MeshPointImpl(new Point3d(1, 1, 0), null, null));
        facet.addVertex(new MeshPointImpl(new Point3d(2, 1, 0), null, null));
        facet.addVertex(new MeshPointImpl(new Point3d(1, 2, 0), null, null));
        facet.addVertex(new MeshPointImpl(new Point3d(2, 0, 0), null, null));
        facet.addVertex(new MeshPointImpl(new Point3d(3, 0, 0), null, null));
        facet.addVertex(new MeshPointImpl(new Point3d(3, 1, 0), null, null));
        return facet;
    }

    /**
     * Unit test for triangle equals
     */
    @Test
    void trianglesEquals() {
        MeshFacet facet = createFacet();

        MeshTriangle tri1 = new MeshTriangle(facet, 0, 1, 2);
        MeshTriangle tri2 = new MeshTriangle(facet, 2, 0, 1);
        MeshTriangle tri3 = new MeshTriangle(facet, 1, 2, 0);
        MeshTriangle tri4 = new MeshTriangle(facet, 1, 2, 3);
        MeshTriangle tri5 = new MeshTriangle(facet, 2, 3, 4);

        Assertions.assertEquals(tri1, tri1);
        Assertions.assertEquals(tri1, tri2);
        Assertions.assertEquals(tri1, tri3);
        Assertions.assertNotEquals(tri1, tri4);
        Assertions.assertNotEquals(tri1, tri5);
        Assertions.assertNotEquals(tri4, tri5);
    }

    /**
     * Unit test for getCommonPoints
     */
    @Test
    void getCommonPoints() {
        MeshFacet facet = createFacet();

        MeshTriangle tri1 = new MeshTriangle(facet, 0, 1, 2);
        MeshTriangle tri2 = new MeshTriangle(facet, 1, 2, 3);
        MeshTriangle tri3 = new MeshTriangle(facet, 2, 3, 4);
        MeshTriangle tri4 = new MeshTriangle(facet, 5, 6, 7);

        List<Point3d> common1 = tri1.getCommonPoints(tri2);
        List<Point3d> common2 = tri2.getCommonPoints(tri3);
        List<Point3d> common3 = tri1.getCommonPoints(tri3);
        List<Point3d> common4 = tri1.getCommonPoints(tri4);

        Assertions.assertEquals(common1.size(), 2);
        Assertions.assertTrue(common1.contains(new Point3d(1, 0, 0)));
        Assertions.assertTrue(common1.contains(new Point3d(1, 1, 0)));

        Assertions.assertEquals(common2.size(), 2);
        Assertions.assertTrue(common2.contains(new Point3d(1, 1, 0)));
        Assertions.assertTrue(common2.contains(new Point3d(2, 1, 0)));


        Assertions.assertEquals(common3.size(), 1);
        Assertions.assertTrue(common3.contains(new Point3d(1, 1, 0)));

        Assertions.assertEquals(common4.size(), 0);
    }

    /**
     * Unit test for getCommonPoints
     */
    @Test
    void checkIntersectionWithPlane() {
        MeshFacet facet = createFacet();

        Vector3d normal = new Vector3d(1, 0, 0);
        double d1 = -1;
        double d2 = -0.5;

        MeshTriangle tri1 = new MeshTriangle(facet, 0, 1, 2);
        MeshTriangle tri2 = new MeshTriangle(facet, 1, 2, 3);
        MeshTriangle tri3 = new MeshTriangle(facet, 2, 3, 4);
        MeshTriangle tri4 = new MeshTriangle(facet, 5, 6, 7);

        Assertions.assertTrue(tri1.checkIntersectionWithPlane(normal, d1));
        Assertions.assertTrue(tri2.checkIntersectionWithPlane(normal, d1));
        Assertions.assertTrue(tri3.checkIntersectionWithPlane(normal, d1));
        Assertions.assertFalse(tri4.checkIntersectionWithPlane(normal, d1));

        Assertions.assertTrue(tri1.checkIntersectionWithPlane(normal, d2));
        Assertions.assertFalse(tri2.checkIntersectionWithPlane(normal, d2));
        Assertions.assertFalse(tri3.checkIntersectionWithPlane(normal, d2));
        Assertions.assertFalse(tri4.checkIntersectionWithPlane(normal, d2));
    }
}
