From 94e5374d88fb6f166489536adcb5048f5d048cc8 Mon Sep 17 00:00:00 2001
From: Maria Kocurekova <xkocure1@fi.muni.cz>
Date: Thu, 17 Dec 2020 00:11:07 +0100
Subject: [PATCH] #36

---
 .../fidentis/analyst/mesh/KdTree/KdNode.java  |  36 ++-
 .../analyst/mesh/KdTree/KdTreeImpl.java       | 265 ++++++++++++------
 .../analyst/mesh/KdTree/kdTreeTest.java       | 152 +++++++++-
 3 files changed, 344 insertions(+), 109 deletions(-)

diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/KdTree/KdNode.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/KdTree/KdNode.java
index 879b7277..77dfc3ac 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/KdTree/KdNode.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/KdTree/KdNode.java
@@ -1,26 +1,36 @@
 package cz.fidentis.analyst.mesh.KdTree;
 
+import cz.fidentis.analyst.mesh.core.MeshFacet;
 import cz.fidentis.analyst.mesh.core.MeshPoint;
 
+import java.util.HashMap;
+import java.util.Map;
+
 
 public class KdNode {
-    private int index;
     private final int depth;
-    private MeshPoint id;
+    private Map<MeshFacet, Integer> facets = new HashMap<>();
 
     private KdNode lesser = null;
     private KdNode greater = null;
     private KdNode parent;
 
-    public KdNode(int index, int depth, MeshPoint id, KdNode parent) {
-        this.index = index;
+    public KdNode(MeshFacet facet,int index, int depth, KdNode parent) {
+        this.facets.putIfAbsent(facet, index);
         this.depth = depth;
-        this.id = id;
+
         this.parent = parent;
+
+    }
+
+    public void addFacet(MeshFacet facet, int index){
+        this.facets.putIfAbsent(facet, index);
     }
 
+    //return only one index (index of MeshPoint in the first MeshFacet)
     public int getIndex() {
-        return index;
+        Map.Entry<MeshFacet, Integer> entry = facets.entrySet().iterator().next();
+        return entry.getValue();
     }
 
     public int getDepth() {
@@ -28,7 +38,8 @@ public class KdNode {
     }
 
     public MeshPoint getId() {
-        return id;
+        Map.Entry<MeshFacet, Integer> entry = facets.entrySet().iterator().next();
+        return entry.getKey().getVertex(entry.getValue());
     }
 
     public KdNode getLesser() {
@@ -39,14 +50,10 @@ public class KdNode {
         return greater;
     }
 
-    public KdNode getParent() {
+   public KdNode getParent() {
         return parent;
     }
 
-    public KdNode setId(MeshPoint id) {
-        this.id = id;
-        return this;
-    }
 
     public KdNode setLesser(KdNode lesser) {
         this.lesser = lesser;
@@ -58,8 +65,13 @@ public class KdNode {
         return this;
     }
 
+    public Map<MeshFacet, Integer> getFacets() {
+        return facets;
+    }
+
     public KdNode setParent(KdNode parent) {
         this.parent = parent;
         return this;
     }
+
 }
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/KdTree/KdTreeImpl.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/KdTree/KdTreeImpl.java
index 732c5760..52c5c890 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/KdTree/KdTreeImpl.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/KdTree/KdTreeImpl.java
@@ -1,154 +1,218 @@
 package cz.fidentis.analyst.mesh.KdTree;
 
+import cz.fidentis.analyst.mesh.core.MeshFacet;
 import cz.fidentis.analyst.mesh.core.MeshPoint;
 
-
-
 import java.util.*;
 
 public class KdTreeImpl {
-    private final KdNode root;
-    private  List<MeshPoint> points;
+    private  KdNode root;
+    private List<MeshFacet> facets;
+
+
+    private Map<MeshPoint, List<IndexOfPoint>> samePoints = new HashMap<>();
 
     private final static int X_AXIS = 0;
     private final static int Y_AXIS = 1;
     private final static int Z_AXIS = 2;
 
 
-/*
-    private static class Pair {
-        private MeshPoint p;
+    private static class IndexOfPoint {
+        private Integer indexInFacet;
+        private MeshFacet facet;
+
+        public IndexOfPoint( int indexInFacet,  MeshFacet facet) {
+            this.indexInFacet = indexInFacet;
+
+            this.facet = facet;
+        }
+
+        public Integer getIndexInFacet() {
+            return indexInFacet;
+        }
+
+        public MeshFacet getFacet() {
+            return facet;
+        }
+
+    }
+
+    private static class Triple {
+        private MeshFacet facet;
+        private MeshPoint point;
         private Integer index;
 
-        public Pair(MeshPoint p, int index) {
-            this.p = p;
-            this. index = index;
+        public Triple(MeshFacet facet, MeshPoint point, int index) {
+            this.facet = facet;
+            this.point = point;
+            this.index = index;
+        }
+
+        public MeshFacet getFacet() {
+            return facet;
         }
 
-        public MeshPoint getP() {
-            return p;
+        public MeshPoint getPoint() {
+            return point;
         }
 
         public Integer getIndex() {
             return index;
         }
-    }*/
+    }
 
-/**
-    private static final Comparator<Pair> X_COMPARATOR = (o1, o2) -> {
-        if (o1.getP().getPosition().x < o2.getP().getPosition().x)
-            return -1;
-        if (o1.getP().getPosition().x > o2.getP().getPosition().x)
-            return 1;
-        return 0;
-    };
 
-    private static final Comparator<Pair> Y_COMPARATOR = (o1, o2) -> {
-        if (o1.getP().getPosition().y < o2.getP().getPosition().y)
-            return -1;
-        if (o1.getP().getPosition().y > o2.getP().getPosition().y)
-            return 1;
-        return 0;
-    };
 
-    private static final Comparator<Pair> Z_COMPARATOR = (o1, o2) -> {
-        if (o1.getP().getPosition().z < o2.getP().getPosition().z)
+    private final Comparator<Integer> xIndexComparatorF = (i1, i2) -> {
+        if (Objects.requireNonNull(findPointFacetIndex(i1)).getPoint().getPosition().x < Objects.requireNonNull(findPointFacetIndex(i2)).getPoint().getPosition().x)
             return -1;
-        if (o1.getP().getPosition().z > o2.getP().getPosition().z)
+        if (Objects.requireNonNull(findPointFacetIndex(i1)).getPoint().getPosition().x > Objects.requireNonNull(findPointFacetIndex(i2)).getPoint().getPosition().x)
             return 1;
-        return 0;
-    };**/
 
+        createSamePoints(i1,i2);
+        return 0;
+    };
 
+    private final Comparator<Integer> yIndexComparatorF = Comparator.comparingDouble(i -> Objects.requireNonNull(findPointFacetIndex(i)).getPoint().getPosition().y);
 
-    private final Comparator<Integer> XIndex_COMPARATOR = Comparator.comparingDouble(i -> this.points.get(i).getPosition().x);
+    private final Comparator<Integer> zIndexComparatorF = Comparator.comparingDouble(i -> Objects.requireNonNull(findPointFacetIndex(i)).getPoint().getPosition().z);
 
-    private final Comparator<Integer> YIndex_COMPARATOR = Comparator.comparingDouble(i -> this.points.get(i).getPosition().y);
 
-    private final Comparator<Integer> ZIndex_COMPARATOR = Comparator.comparingDouble(i -> this.points.get(i).getPosition().z);
+    public  KdTreeImpl(List<MeshFacet> facets) {
+        if(facets == null ||  facets.isEmpty() || facets.get(0).getVertices().isEmpty() ){
+            this.root = null;
+            this.facets = null;
+            return;
+        }
 
-/*
-    private static final Comparator<Pair> X_COMPARATOR = Comparator.comparingDouble(o -> o.getP().getPosition().x);
+        int countOfVertices = 0;
+        for (MeshFacet facet : facets) {
+            countOfVertices += facet.getVertices().size();
+        }
 
-    private static final Comparator<Pair> Y_COMPARATOR = Comparator.comparingDouble(o -> o.getP().getPosition().y);
 
-    private static final Comparator<Pair> Z_COMPARATOR = Comparator.comparingDouble(o -> o.getP().getPosition().z);
-*/
 
+        this.facets = facets;
 
-    public KdTreeImpl(List<MeshPoint> points) {
-        if(points == null || points.isEmpty()){
-            this.root = null;
-            this.points = null;
-            return;
-        }
+        List<Integer> sortedByX = sortPointsF( X_AXIS);
+        List<Integer> sortedByY = sortPointsF( Y_AXIS);
+        List<Integer> sortedByZ = sortPointsF( Z_AXIS);
 
-        this.points = points;
+        List<Integer> uniqueSortedX = new LinkedList<>();
+        List<Integer> uniqueSortedY = new LinkedList<>();
+        List<Integer> uniqueSortedZ = new LinkedList<>();
 
-        List<Integer> sortedByX = sortPoints( X_AXIS/*, points*/);
-        List<Integer> sortedByY = sortPoints( Y_AXIS/*, points*/);
-        List<Integer> sortedByZ = sortPoints( Z_AXIS/*, points*/);
 
-        root = buildTree(null, sortedByX, sortedByY, sortedByZ, 0/*, points*/);
+        if (!samePoints.isEmpty()) {
+            for (int i = 0; i < countOfVertices; i++) {
+                if (samePoints.containsKey(Objects.requireNonNull(findPointFacetIndex(sortedByX.get(i))).getPoint())) {
+                    Objects.requireNonNull(findPointFacetIndex(sortedByX.get(i)));
+                    uniqueSortedX.add(sortedByX.get(i));
+                }
+                if (samePoints.containsKey(Objects.requireNonNull(findPointFacetIndex(sortedByY.get(i))).getPoint())) {
+                    Objects.requireNonNull(findPointFacetIndex(sortedByY.get(i)));
+                    uniqueSortedY.add(sortedByY.get(i));
+                }
+                if (samePoints.containsKey(Objects.requireNonNull(findPointFacetIndex(sortedByZ.get(i))).getPoint())) {
+                    Objects.requireNonNull(findPointFacetIndex(sortedByZ.get(i)));
+                    uniqueSortedZ.add(sortedByZ.get(i));
+                }
+            }
 
+            root = buildTreeF(null, uniqueSortedX, uniqueSortedY, uniqueSortedZ, 0);
+        } else {
+            root = buildTreeF(null, sortedByX, sortedByY, sortedByZ, 0);
+        }
     }
 
-    private boolean comparePointsOnLevel(MeshPoint p1, MeshPoint p2, int level){
-        if(level % 3 == 0){
-            return p1.getPosition().x <= p2.getPosition().x;
-        }else if(level % 3 == 1){
-            return p1.getPosition().y <= p2.getPosition().y;
-        }else if(level % 3 == 2){
-            return p1.getPosition().z <= p2.getPosition().z;
+    private Triple findPointFacetIndex(int index) {
+        Triple result;
+        int countOfCheckedVertices = 0;
+        for (MeshFacet facet : facets) {
+            if (countOfCheckedVertices + facet.getVertices().size() > index) {
+                result = new Triple(facet, facet.getVertex(index - countOfCheckedVertices), index - countOfCheckedVertices);
+                return result;
+            }
+            countOfCheckedVertices += facet.getVertices().size();
         }
+        return null;
+    }
 
-        return false;
+
+    private boolean checkSamePoints(MeshPoint p1, MeshPoint p2){
+        return p1.getPosition().x == p2.getPosition().x
+                && p1.getPosition().y == p2.getPosition().y
+                && p1.getPosition().z == p2.getPosition().z;
     }
 
+    public void createSamePoints(Integer i1, Integer i2) {
+        Triple firstP = findPointFacetIndex(i1);
+        Triple secondP = findPointFacetIndex(i2);
+        List<IndexOfPoint> allFacetsOfPoint = new LinkedList<>();
 
-    private List<Integer> sortPoints(/*List<Integer> points,*/ int level /*List<MeshPoint> p*/){
-        List<Integer> sortedListIndex = new ArrayList<>(this.points.size());
-        for(int i = 0; i < points.size(); i++){
-            sortedListIndex.add(i);
+        if(checkSamePoints(Objects.requireNonNull(firstP).getPoint(), Objects.requireNonNull(secondP).getPoint())) {
+
+            if(samePoints.containsKey(firstP.getPoint())) {
+                allFacetsOfPoint.addAll(samePoints.get(firstP.getPoint()));
+            } else {
+                allFacetsOfPoint.add(new IndexOfPoint(firstP.getIndex(), firstP.getFacet()));
+            }
+
+            allFacetsOfPoint.add(new IndexOfPoint(secondP.getIndex(),secondP.getFacet()));
+            samePoints.putIfAbsent(firstP.getPoint(), allFacetsOfPoint);
         }
+    }
+
 
-        /*List<Pair> sortedListPairs = new ArrayList<>(p.size());
 
-        for (int i = 0; i < p.size(); i++ ) {
-            sortedListPairs.add(new Pair(p.get(i), i));
+    private List<Integer> sortPointsF(int level){
+        int countOfVertices = 0;
+        for (MeshFacet facet : facets) {
+            countOfVertices += facet.getVertices().size();
+        }
+        List<Integer> sortedListIndex = new ArrayList<>(countOfVertices);
+        for(int i = 0; i < countOfVertices; i++){
+            sortedListIndex.add(i);
         }
 
         if(level % 3 == 0){
-            sortedListPairs.sort(X_COMPARATOR);
+            sortedListIndex.sort(xIndexComparatorF);
         }else if(level % 3 == 1){
-            sortedListPairs.sort(Y_COMPARATOR);
+            sortedListIndex.sort(yIndexComparatorF);
         }else if(level % 3 == 2){
-            sortedListPairs.sort(Z_COMPARATOR);
+            sortedListIndex.sort(zIndexComparatorF);
         }
+        return sortedListIndex;
 
-        for(Pair pair : sortedListPairs) {
-            sortedListIndex.add(pair.getIndex());
-        }
-        return sortedListIndex;*/
+    }
 
+    private boolean comparePointsOnLevel(MeshPoint p1, MeshPoint p2, int level){
         if(level % 3 == 0){
-            sortedListIndex.sort(XIndex_COMPARATOR);
+            return p1.getPosition().x <= p2.getPosition().x;
         }else if(level % 3 == 1){
-            sortedListIndex.sort(YIndex_COMPARATOR);
+            return p1.getPosition().y <= p2.getPosition().y;
         }else if(level % 3 == 2){
-            sortedListIndex.sort(ZIndex_COMPARATOR);
+            return p1.getPosition().z <= p2.getPosition().z;
         }
-        return sortedListIndex;
 
+        return false;
+    }
+
+
+    private void setFacetsOfNode(KdNode node, int midIndex) {
+        for (int i = 0; i < samePoints.get(Objects.requireNonNull(findPointFacetIndex(midIndex)).getPoint()).size(); i++) {
+            IndexOfPoint point = samePoints.get(Objects.requireNonNull(findPointFacetIndex(midIndex)).getPoint()).get(i);
+            node.addFacet(point.getFacet(), point.getIndexInFacet());
+        }
     }
 
 
-    private KdNode buildTree(KdNode parent, List<Integer> byX, List<Integer> byY, List<Integer> byZ, int level/*, List<MeshPoint> points*/) {
+    private KdNode buildTreeF(KdNode parent, List<Integer> byX, List<Integer> byY, List<Integer> byZ, int level) {
         KdNode node = null;
         int mid;
         int midIndex;
 
-        if(byX.size() > 0 && byY.size() > 0 && byZ.size() > 0){
+        if (byX.size() > 0 && byY.size() > 0 && byZ.size() > 0) {
             mid = (byX.size() / 2);
 
             List<Integer> leftX = new ArrayList<>(mid);
@@ -158,21 +222,34 @@ public class KdTreeImpl {
             //split lists in half, set middle element as new KdNode to be returned
             //first list to be split based on level, rest so that they contain points in first list
             //but also keep the ordering by their axis
-            if (level % 3 == 0){
+
+            if (level % 3 == 0) {
                 midIndex = byX.get(mid);
-                node = new KdNode(midIndex, level, this.points.get(byX.get(mid)), parent);
+                node = new KdNode(Objects.requireNonNull(findPointFacetIndex(midIndex)).getFacet(), Objects.requireNonNull(findPointFacetIndex(midIndex)).getIndex(), level, parent);
+
+                if (samePoints.containsKey(Objects.requireNonNull(findPointFacetIndex(midIndex)).getPoint())) {
+                   setFacetsOfNode(node, midIndex);
+                }
 
                 splitTree(mid, leftX, byX, leftY, byY, leftZ, byZ);
 
-            }else if(level % 3 == 1){
+            } else if (level % 3 == 1) {
                 midIndex = byY.get(mid);
-                node = new KdNode(midIndex, level, this.points.get(byY.get(mid)), parent);
+                node = new KdNode(Objects.requireNonNull(findPointFacetIndex(midIndex)).getFacet(), Objects.requireNonNull(findPointFacetIndex(midIndex)).getIndex(), level, parent);
+
+                if (samePoints.containsKey(Objects.requireNonNull(findPointFacetIndex(midIndex)).getPoint())) {
+                    setFacetsOfNode(node, midIndex);
+                }
 
                 splitTree(mid, leftY, byY, leftX, byX, leftZ, byZ);
 
-            }else{
+            } else {
                 midIndex = byZ.get(mid);
-                node = new KdNode(midIndex, level, this.points.get(byZ.get(mid)), parent);
+                node = new KdNode(Objects.requireNonNull(findPointFacetIndex(midIndex)).getFacet(), Objects.requireNonNull(findPointFacetIndex(midIndex)).getIndex(), level, parent);
+
+                if (samePoints.containsKey(Objects.requireNonNull(findPointFacetIndex(midIndex)).getPoint())) {
+                    setFacetsOfNode(node, midIndex);
+                }
 
                 splitTree(mid, leftZ, byZ, leftY, byY, leftX, byX);
 
@@ -186,13 +263,14 @@ public class KdTreeImpl {
             leftY.removeAll(Collections.singleton(midIndex));
             leftZ.removeAll(Collections.singleton(midIndex));
 
-            node.setLesser(buildTree(node, leftX, leftY, leftZ, level + 1/*, points*/));
-            node.setGreater(buildTree(node, byX, byY, byZ, level + 1/*, points*/));
+            node.setLesser(buildTreeF(node, leftX, leftY, leftZ, level + 1));
+            node.setGreater(buildTreeF(node, byX, byY, byZ, level + 1));
         }
 
         return node;
     }
 
+
     private void splitTree(int mid, List<Integer> leftMain, List<Integer> mainList, List<Integer> leftSecond,
                            List<Integer> secondList, List<Integer> leftThird, List<Integer> thirdList){
         for (int i = 0; i < mid; i++) {
@@ -224,6 +302,7 @@ public class KdTreeImpl {
         return nn.getId();
     }
 
+
     public boolean containPoint(MeshPoint p){
         MeshPoint found = nearestNeighbour(p);
 
@@ -321,6 +400,16 @@ public class KdTreeImpl {
 
     }
 
+    public Integer nearestNeighbourCountOfFacets(MeshPoint p){
+        KdNode nn = nearestNeighbourNode(p);
+
+        if(nn == null){
+            return null;
+        }
+
+        return nn.getFacets().size();
+    }
+
     /**
      * Find index of MeshPoint in MeshFacetImpl -> vertices
      * @param p MeshPoint
diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/KdTree/kdTreeTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/KdTree/kdTreeTest.java
index 4d4a8c11..eeec7de1 100644
--- a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/KdTree/kdTreeTest.java
+++ b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/KdTree/kdTreeTest.java
@@ -1,4 +1,6 @@
 package cz.fidentis.analyst.mesh.KdTree;
+import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
 import cz.fidentis.analyst.mesh.core.MeshPoint;
 import cz.fidentis.analyst.mesh.core.MeshPointImpl;
 import org.junit.jupiter.api.Test;
@@ -24,9 +26,13 @@ public class kdTreeTest {
     public void testPut(){
         MeshPoint p = new MeshPointImpl(position,normalAndTextCoord,normalAndTextCoord);
 
-        List<MeshPoint> points = new LinkedList<>();
-        points.add(p);
-        KdTreeImpl tree = new KdTreeImpl(points);
+       // List<MeshPoint> points = new LinkedList<>();
+        List<MeshFacet> facets = new LinkedList<>();
+       // points.add(p);
+        MeshFacet facet = new MeshFacetImpl();
+        facet.addVertex(p);
+        facets.add(facet);
+        KdTreeImpl tree = new KdTreeImpl(facets);
 
         assertTrue(tree.containPoint(p));
     }
@@ -35,8 +41,10 @@ public class kdTreeTest {
     public void testPutNothing(){
         MeshPoint p = new MeshPointImpl(position,normalAndTextCoord,normalAndTextCoord);
 
-        List<MeshPoint> points = new LinkedList<>();
-        KdTreeImpl tree = new KdTreeImpl(points);
+      //  List<MeshPoint> points = new LinkedList<>();
+        List<MeshFacet> facets2 = new LinkedList<>();
+        MeshFacet facet = new MeshFacetImpl();
+        KdTreeImpl tree = new KdTreeImpl(facets2);
 
         assertFalse(tree.containPoint(p));
     }
@@ -68,15 +76,22 @@ public class kdTreeTest {
 
     @Test
     public void testFindClosestAlreadyIn(){
+        List<MeshFacet> facets = new LinkedList<>();
+
+        MeshFacet facet = new MeshFacetImpl();
+
+
         List<MeshPoint> points = new LinkedList<>();
         Vector3d positionOfPoints;
 
         for(int i = 0; i < 10; i++){
             positionOfPoints = new Vector3d(0.1f * i, 0.5f * i, 0.7f * i);
             points.add(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
+            facet.addVertex(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
         }
+        facets.add(facet);
+        KdTreeImpl tree = new KdTreeImpl(facets);
 
-        KdTreeImpl tree = new KdTreeImpl(points);
         Random r = new Random();
 
         MeshPoint p = points.get(r.nextInt(points.size()));
@@ -87,16 +102,99 @@ public class kdTreeTest {
     }
 
     @Test
-    public void testFindClosestNotInTree(){
+    public void testFindClosestAlreadyInTwoFacets(){
+        List<MeshFacet> facets = new LinkedList<>();
+
+        MeshFacet facet1 = new MeshFacetImpl();
+        MeshFacet facet2 = new MeshFacetImpl();
+
+
         List<MeshPoint> points = new LinkedList<>();
         Vector3d positionOfPoints;
 
+        for(int i = 0; i < 5; i++){
+            positionOfPoints = new Vector3d(0.1f * i, 0.5f * i, 0.7f * i);
+            points.add(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
+            facet1.addVertex(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
+        }
+        for(int i = 5; i < 10; i++){
+            positionOfPoints = new Vector3d(0.1f * i, 0.5f * i, 0.7f * i);
+            points.add(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
+            facet2.addVertex(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
+        }
+        facets.add(facet1);
+        facets.add(facet2);
+        KdTreeImpl tree = new KdTreeImpl(facets);
+
+        Random r = new Random();
+
+        MeshPoint p = points.get(r.nextInt(points.size()));
+        MeshPoint found = tree.nearestNeighbour(p);
+
+        assertEquals(found, p);
+        assertEquals(0.0f, distancePoints(found, p));
+    }
+
+    @Test
+    public void testCountOfFacets(){
+        List<MeshFacet> facets = new LinkedList<>();
+
+        MeshFacet facet1 = new MeshFacetImpl();
+        MeshFacet facet2 = new MeshFacetImpl();
+
+
+        List<MeshPoint> points = new LinkedList<>();
+        Vector3d positionOfPoints;
+
+        for(int i = 0; i < 10; i++){
+            positionOfPoints = new Vector3d(0.1f * i, 0.5f * i, 0.7f * i);
+            points.add(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
+            facet1.addVertex(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
+        }
         for(int i = 0; i < 10; i++){
             positionOfPoints = new Vector3d(0.1f * i, 0.5f * i, 0.7f * i);
             points.add(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
+            facet2.addVertex(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
         }
+        facets.add(facet1);
+        facets.add(facet2);
+        KdTreeImpl tree = new KdTreeImpl(facets);
 
-        KdTreeImpl tree = new KdTreeImpl(points);
+        Random r = new Random();
+
+        MeshPoint p = points.get(r.nextInt(points.size()));
+        MeshPoint found = tree.nearestNeighbour(p);
+
+        assertEquals(found, p);
+        assertEquals(2,tree.nearestNeighbourCountOfFacets(p));
+    }
+
+    @Test
+    public void testFindClosestNotInTreeTwoFacets(){
+        List<MeshFacet> facets = new LinkedList<>();
+
+        MeshFacet facet1 = new MeshFacetImpl();
+        MeshFacet facet2 = new MeshFacetImpl();
+
+
+        List<MeshPoint> points = new LinkedList<>();
+        Vector3d positionOfPoints;
+
+        for(int i = 0; i < 5; i++){
+            positionOfPoints = new Vector3d(0.1f * i, 0.5f * i, 0.7f * i);
+            points.add(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
+            facet1.addVertex(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
+        }
+        for(int i =5; i < 10; i++){
+            positionOfPoints = new Vector3d(0.1f * i, 0.5f * i, 0.7f * i);
+            points.add(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
+            facet2.addVertex(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
+        }
+
+
+        facets.add(facet1);
+        facets.add(facet2);
+        KdTreeImpl tree = new KdTreeImpl(facets);
 
         MeshPoint p = new MeshPointImpl(new Vector3d(2.5f, 0.3f, 1.2f), normalAndTextCoord,normalAndTextCoord);
         MeshPoint found = tree.nearestNeighbour(p);
@@ -106,7 +204,43 @@ public class kdTreeTest {
         assertEquals(found, seq);
         assertEquals(distancePoints(found, p), distancePoints(seq, p));
     }
+    @Test
+    public void testIndexFoundTwoFacetsNoDuplicates(){
+        List<MeshFacet> facets = new LinkedList<>();
+
+        MeshFacet facet1 = new MeshFacetImpl();
+        MeshFacet facet2 = new MeshFacetImpl();
+
 
+        List<MeshPoint> points = new LinkedList<>();
+        Vector3d positionOfPoints;
+
+        for(int i = 5; i < 20; i++){
+            positionOfPoints = new Vector3d(0.1f * i, 0.5f * i, 0.7f * i);
+            points.add(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
+            facet1.addVertex(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
+        }
+        for(int i =0; i < 5; i++){
+            positionOfPoints = new Vector3d(0.1f * i, 0.5f * i, 0.7f * i);
+            points.add(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
+            facet2.addVertex(new MeshPointImpl(positionOfPoints, normalAndTextCoord, normalAndTextCoord));
+        }
+
+
+        facets.add(facet1);
+        facets.add(facet2);
+        KdTreeImpl tree = new KdTreeImpl(facets);
+
+        Random r = new Random();
+
+        MeshPoint p = points.get(r.nextInt(points.size()));
+        int found = tree.nearestNeighbourIndex(p);
+
+        assertEquals(points.get(found), p);
+        assertEquals(0.0f, distancePoints(points.get(found), p));
+    }
+
+/*
     @Test
     public void testIndexFound(){
         List<MeshPoint> points = new LinkedList<>();
@@ -129,7 +263,7 @@ public class kdTreeTest {
 
         assertEquals(points.get(found), p);
         assertEquals(0.0f, distancePoints(points.get(found), p));
-    }
+    }*/
 
 }
 
-- 
GitLab