package cz.fidentis.analyst.visitors.mesh;

import cz.fidentis.analyst.mesh.core.CornerTableRow;
import cz.fidentis.analyst.mesh.core.MeshFacet;
import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
import cz.fidentis.analyst.mesh.core.MeshModel;
import cz.fidentis.analyst.mesh.core.MeshPointImpl;
import java.util.List;
import java.util.Map;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;

/**
 *
 * @author oslejsek
 */
public class MeshDistanceToTrianglesTest {
    
    protected MeshFacet getTrivialFacet(double offset, double size) {
        MeshFacet facet = new MeshFacetImpl();
        facet.addVertex(new MeshPointImpl(new Point3d(0, 0, offset), new Vector3d(0, 0, 1), new Vector3d()));
        facet.addVertex(new MeshPointImpl(new Point3d(size, 0, offset), new Vector3d(0, 0, 1), new Vector3d()));
        facet.addVertex(new MeshPointImpl(new Point3d(0, size, offset), new Vector3d(0, 0, 1), new Vector3d()));

        facet.getCornerTable().addRow(new CornerTableRow(0, -1));
        facet.getCornerTable().addRow(new CornerTableRow(1, -1));
        facet.getCornerTable().addRow(new CornerTableRow(2, -1));

        return facet;
    }
    
    protected void distTest(double expectedDist, MeshDistanceToTriangles vis) {
        MeshModel model = new MeshModel();
        MeshFacet facet = getTrivialFacet(1.5, 1);
        model.addFacet(facet);
        
        model.compute(vis);
        assertEquals(expectedDist, vis.getDistance());
        
        Map<MeshFacet, List<Point3d>> closestFacets = vis.getNearestPoints();
        MeshFacet firstFacet = closestFacets.keySet().stream().findFirst().get();
        assertEquals(1, closestFacets.size());
        assertEquals(1, closestFacets.get(firstFacet).size());
        assertTrue(closestFacets.containsKey(facet));
        assertEquals(new Vector3d(0, 0, 1.5), closestFacets.get(firstFacet).get(0));
    }
    
    @Test
    public void absoluteDistTest() {
        MeshDistanceToTriangles vis = new MeshDistanceToTriangles(new Point3d(0,0,0)); // sequentially
        distTest(1.5, vis);
    }

   @Test
    public void exactMatchTest() {
        MeshDistanceToTriangles vis = new MeshDistanceToTriangles(new Point3d(0, 0, 1.5)); // relative dist, sequentially
        distTest(0, vis);
    }
    
    @Test
    public void concurrencyTest() {
        MeshDistanceToTriangles vis = new MeshDistanceToTriangles(new Point3d(0,0,0)); // absolute dist, concurrently
        distTest(1.5, vis);
    }
    
}
