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 f0c30dd5491fffbc6f92e66ee3f905226a4580fa..879b727737c243ae14bb98f4e32c28cb809b3baf 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 @@ -5,7 +5,6 @@ import cz.fidentis.analyst.mesh.core.MeshPoint; public class KdNode { private int index; - // represents index of vertices in the class MashFacetImpl in the attribute vertices private final int depth; private MeshPoint id; 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 43e339e56f7158a952e78594f73af2fe6a461734..d287b1d31f5a63dfadf48ac3f65e1f4fd28e60f3 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 @@ -3,42 +3,75 @@ package cz.fidentis.analyst.mesh.KdTree; import cz.fidentis.analyst.mesh.core.MeshPoint; -import javax.vecmath.Vector3d; + import java.util.*; public class KdTreeImpl { private final KdNode root; - private final List<MeshPoint> points; - - //private Map<MeshPoint, Integer> pointsWithIndex = 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 Integer index; + public Pair(MeshPoint p, int index) { + this.p = p; + this. index = index; + } + public MeshPoint getP() { + return p; + } - public KdTreeImpl(List<MeshPoint> points) { - if(points == null || points.isEmpty()){ - this.root = null; - this.points = null; - return; + public Integer getIndex() { + return index; } + } - this.points = points; +/** + 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; + }; - List<Integer> pointsCopy = new ArrayList<>(points.size()); - for(int i = 0; i < points.size(); i++){ - pointsCopy.add(i); - } + 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) + return -1; + if (o1.getP().getPosition().z > o2.getP().getPosition().z) + return 1; + return 0; + };**/ - pointsCopy = deleteDuplicates(points); //(pointsCopy, - List<Integer> sortedByX = sortPoints(pointsCopy, X_AXIS, points); - List<Integer> sortedByY = sortPoints(pointsCopy, Y_AXIS, points); - List<Integer> sortedByZ = sortPoints(pointsCopy, Z_AXIS, points); + private static final Comparator<Pair> X_COMPARATOR = Comparator.comparingDouble(o -> o.getP().getPosition().x); + 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); + + public KdTreeImpl(List<MeshPoint> points) { + if(points == null || points.isEmpty()){ + this.root = null; + return; + } + + 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); @@ -56,77 +89,28 @@ public class KdTreeImpl { return false; } - private List<Integer> merge(List<Integer> left, List<Integer> right, int level, List<MeshPoint> points){ - List<Integer> mergedList = new ArrayList<>(left.size() + right.size()); - int fromLeft = 0; - int fromRight = 0; + private List<Integer> sortPoints(/*List<Integer> points,*/ int level, List<MeshPoint> p){ + List<Integer> sortedListIndex = new ArrayList<>(p.size()); + List<Pair> sortedListPairs = new ArrayList<>(p.size()); - while(fromLeft < left.size() || fromRight < right.size()){ - if(fromLeft < left.size() && fromRight < right.size()){ - if(comparePointsOnLevel(points.get(left.get(fromLeft)), points.get(right.get(fromRight)), level)){ - mergedList.add(left.get(fromLeft)); - fromLeft++; - }else{ - mergedList.add(right.get(fromRight)); - fromRight++; - } - }else if(fromLeft < left.size()){ - mergedList.add(left.get(fromLeft)); - fromLeft++; - }else if(fromRight < right.size()){ - mergedList.add(right.get(fromRight)); - fromRight++; - } + for (int i = 0; i < p.size(); i++ ) { + sortedListPairs.add(new Pair(p.get(i), i)); } - return mergedList; - } - - private List<Integer> mergeSort(List<Integer> points, int level, List<MeshPoint> p){ - if(points.size() <= 1){ - return points; + if(level % 3 == 0){ + sortedListPairs.sort(X_COMPARATOR); + }else if(level % 3 == 1){ + sortedListPairs.sort(Y_COMPARATOR); + }else if(level % 3 == 2){ + sortedListPairs.sort(Z_COMPARATOR); } - List<Integer> left; - List<Integer> right; - - int mid = (points.size()/2); - - left = points.subList(0, mid); - right = points.subList(mid, points.size()); - - - left = mergeSort(left, level, p); - right = mergeSort(right, level, p); - - return merge(left, right, level, p); - } - - private List<Integer> sortPoints(List<Integer> points, int level, List<MeshPoint> p){ - List<Integer> sortedList = new ArrayList<>(points.size()); - - sortedList.addAll(points); - - sortedList = mergeSort(sortedList,level, p); - - return sortedList; - - } - - - private List<Integer> deleteDuplicates(List<MeshPoint> points){ // List<Integer> list - List<Vector3d> noDuplicates = new ArrayList<>(); - List<Integer> noDupIndex = new ArrayList<>(); - - for(int i = 0; i < points.size(); i++){ - if(!noDuplicates.contains(points.get(i).getPosition())){ - noDuplicates.add(points.get(i).getPosition()); - noDupIndex.add(i); - } + for(Pair pair : sortedListPairs) { + sortedListIndex.add(pair.getIndex()); } + return sortedListIndex; - return noDupIndex; } diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/KdTree/KdTreeImplTests.java b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/KdTree/kdTreeTest.java similarity index 71% rename from MeshModel/src/main/java/cz/fidentis/analyst/mesh/KdTree/KdTreeImplTests.java rename to MeshModel/src/test/java/cz/fidentis/analyst/mesh/KdTree/kdTreeTest.java index f6cf8f5e72bbee8c7d8e5c763cbcc8e27498ea83..4d4a8c11f5e93f800aaadcbbcb3dcaa1c90b795c 100644 --- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/KdTree/KdTreeImplTests.java +++ b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/KdTree/kdTreeTest.java @@ -1,21 +1,25 @@ package cz.fidentis.analyst.mesh.KdTree; - import cz.fidentis.analyst.mesh.core.MeshPoint; import cz.fidentis.analyst.mesh.core.MeshPointImpl; -import org.junit.Test; +import org.junit.jupiter.api.Test; import javax.vecmath.Vector3d; import java.util.LinkedList; import java.util.List; import java.util.Random; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertTrue; + + + +public class kdTreeTest { -public class KdTreeImplTests { private Vector3d position = new Vector3d(0.1f, 0.5f, 0.7f); private Vector3d normalAndTextCoord = new Vector3d(0,0,0); + @Test public void testPut(){ MeshPoint p = new MeshPointImpl(position,normalAndTextCoord,normalAndTextCoord); @@ -65,7 +69,7 @@ public class KdTreeImplTests { @Test public void testFindClosestAlreadyIn(){ List<MeshPoint> points = new LinkedList<>(); - Vector3d positionOfPoints; + Vector3d positionOfPoints; for(int i = 0; i < 10; i++){ positionOfPoints = new Vector3d(0.1f * i, 0.5f * i, 0.7f * i); @@ -79,7 +83,7 @@ public class KdTreeImplTests { MeshPoint found = tree.nearestNeighbour(p); assertEquals(found, p); - assertTrue(distancePoints(found, p) == 0.0f); + assertEquals(0.0f, distancePoints(found, p)); } @Test @@ -100,7 +104,33 @@ public class KdTreeImplTests { MeshPoint seq = findClosestSequential(points, p); assertEquals(found, seq); - assertTrue(distancePoints(found, p) == distancePoints(seq, p)); + assertEquals(distancePoints(found, p), distancePoints(seq, p)); + } + + @Test + public void testIndexFound(){ + List<MeshPoint> points = new LinkedList<>(); + Vector3d positionOfPoints; + + 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)); + } + 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)); + } + + KdTreeImpl tree = new KdTreeImpl(points); + 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)); } } + +