【问题标题】:How to find center dots of given dots in radius of 16 (x;z)?如何找到半径为 16(x;z)的给定点的中心点?
【发布时间】:2016-07-24 00:15:41
【问题描述】:

我正在尝试打印中心点的位置。比较点的半径必须为 16。仅当从中心计算的一个位置超过 5 个点时才打印。

中心点是,最接近所有附近的点

我的代码给了我误报和重复。方法:

    HashMap<Location, HashSet<Location>> map = new HashMap<Location, HashSet<Location>>();
    for (LocationCopy loc : locs) {
            HashSet<LocationCopy> locsCopy = new HashSet<LocationCopy>(locs);
            locsCopy.remove(loc);
            for (LocationCopy loc2 : locsCopy) {
                if (distance(loc2.getX(),loc.getX(),loc2.getZ(),loc.getZ()) <= 16) {
                    if (!map.containsKey(loc.getLoc())) {
                        HashSet<Location> hs = new HashSet<Location>();
                        hs.add(loc2.getLoc());
                        map.put(loc2.getLoc(), hs);
                    } else {
                        HashSet<Location> hs = map.get(loc.getLoc());
                        hs.add(loc2.getLoc());
                        map.put(loc2.getLoc(), hs);
                    }
                }
            }

        }

        for (Location loc : map.keySet()) {
            if (map.get(loc).size() > 5) {
                write("More than " + map.get(loc).size() + locToString(loc) + ": " + getLocs(map.get(loc)) + "<br>", fileName, beta);
            }
        }

    private double distance(double x1, double x2, double z1, double z2){
        return Math.sqrt(Math.pow(x2-x1,2)+Math.pow(z2-z1,2));
    }

类:

    public class LocationCopy {
        private int x, y, z;
        private String world;

        public LocationCopy(int x, int y, int z, String world) {
            this.x = x;
            this.y = y;
            this.z = z;
            this.world = world;
        }

        public LocationCopy(Location spawner) {
            this.x = spawner.getBlockX();
            this.y = spawner.getBlockY();
            this.z = spawner.getBlockZ();
            this.world = spawner.getWorld().getName();
        }

        public int getX(){
            return x;
        }

        public int getZ(){
            return z;
        }

        public Location getLoc() {
            return new Location(Bukkit.getWorld(world), x, y, z);
        }

    }

【问题讨论】:

    标签: java coordinates coordinate-systems


    【解决方案1】:

    您的代码中存在一些小问题:

    • map.put(loc2.getLoc(), hs); 应该改为 map.put(loc.getLoc(), hs);
    • 您需要将hashCode 方法添加到您的类中,否则您使用的HashSets 将无法识别代表相同位置的对象
    • 您只搜索点组,而不是它们的中心

    解决方案可能如下所示(在 LocationCopy 类中实现了您的方法,因为您的问题中没有显示任何类):

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    public class LocationCopy {
    
        private int x, y, z;
        //private String world;
    
        public LocationCopy(int x/*, int y*/, int z/*, String world*/) {
            this.x = x;
            //this.y = y;
            this.z = z;
            //this.world = world;
        }
    
        public LocationCopy(Location spawner) {
            this.x = spawner.getBlockX();
            this.y = spawner.getBlockY();
            this.z = spawner.getBlockZ();
            //this.world = spawner.getWorld().getName();
        }
    
        //EDIT added toString method (just for better printing and debugging)
        @Override
        public String toString() {
            return "LocationCopy [x=" + x + ", y=" + y + ", z=" + z + "]";
        }
    
        //EDIT: added hashCode method that is needed for the HashSets to identify objects that represent the same location
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + x;
            result = prime * result + y;
            result = prime * result + z;
            return result;
        }
    
        //EDIT: added equals method (not really needed, but better to have one...)
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            LocationCopy other = (LocationCopy) obj;
            if (x != other.x)
                return false;
            if (y != other.y)
                return false;
            if (z != other.z)
                return false;
            return true;
        }
    
        public int getX() {
            return x;
        }
    
        public int getZ() {
            return z;
        }
    
        public Location getLoc() {
            return new Location(x, y, z);
        }
    
        public static void main(String[] args) {
            List<LocationCopy> locs = createLocs();
    
            HashMap<Location, HashSet<Location>> map = new HashMap<Location, HashSet<Location>>();
            for (LocationCopy loc : locs) {
                HashSet<LocationCopy> locsCopy = new HashSet<LocationCopy>(locs);
                locsCopy.remove(loc);
                for (LocationCopy loc2 : locsCopy) {
                    if (distance(loc2.getX(), loc.getX(), loc2.getZ(), loc.getZ()) <= 16) {
                        if (!map.containsKey(loc.getLoc())) {
                            HashSet<Location> hs = new HashSet<Location>();
                            hs.add(loc2.getLoc());
                            map.put(loc.getLoc(), hs);//EDIT: changed loc2 to loc
                        }
                        else {
                            HashSet<Location> hs = map.get(loc.getLoc());
                            hs.add(loc2.getLoc());
                            map.put(loc.getLoc(), hs);//EDIT: changed loc2 to loc
                        }
                    }
                }
    
            }
    
            //EDIT: selecting groups for finding the center
            Set<Set<Location>> groups = new HashSet<Set<Location>>();
    
            for (Location loc : map.keySet()) {
                if (map.get(loc).size() > 5) {
                    //EDIT: don't know what write does -> using System.out.println instead
                    //write("More than " + map.get(loc).size() + locToString(loc) + ": " + getLocs(map.get(loc)) + "<br>", fileName, beta);
                    System.out.println("More than " + map.get(loc).size() + " " + locToString(loc) + ": " + /*getLocs(map.get(loc)) + */"<br>");
    
                    //EDIT: create groups to find the center points
                    Set<Location> group = new HashSet<Location>();
                    group.addAll(map.get(loc));
                    group.add(loc);
    
                    groups.add(group);
                }
            }
    
            //EDIT: find the center of the group
            for (Set<Location> group : groups) {
                Location center = findCenter(group);
    
                System.out.println("center found: " + center);
            }
        }
    
        /**
         * Find the center of each group by calculating the summed distance from each point to every other point.
         * 
         * The point that has the minimum summed distance to every other point is the center.
         */
        private static Location findCenter(Set<Location> group) {
            if (group.isEmpty()) {
                throw new IllegalArgumentException("The group mussn't be empty");
            }
    
            List<LocationDistance> summedDistances = new ArrayList<LocationDistance>(group.size());
    
            for (Location loc : group) {
                LocationDistance dist = new LocationDistance(loc, 0);
                //sum up the distance to each location in the group
                for (Location loc2 : group) {
                    double distance = distance(loc.getBlockX(), loc2.getBlockX(), loc.getBlockZ(), loc2.getBlockZ());
                    dist.setDistance(dist.getDistance() + distance);
                }
                summedDistances.add(dist);
            }
    
            //sort the list (LocationDistance implements Comparable to do this)
            Collections.sort(summedDistances);
    
            //the first item in the list is the center
            return summedDistances.get(0).getLocation();
        }
    
        private static List<LocationCopy> createLocs() {
            List<LocationCopy> locs = new ArrayList<LocationCopy>();
    
            //trying to create the example from the image in your question
            locs.add(new LocationCopy(0, 0));
            locs.add(new LocationCopy(2, 0));
            locs.add(new LocationCopy(5, 0));
            locs.add(new LocationCopy(1, 2));
            locs.add(new LocationCopy(2, 1));//center
            locs.add(new LocationCopy(4, 1));
            locs.add(new LocationCopy(3, 2));//adding a new point because otherwhise it will never be enough for a group greater than 5
            locs.add(new LocationCopy(10, 30));
            locs.add(new LocationCopy(12, 31));
            locs.add(new LocationCopy(15, 31));
            locs.add(new LocationCopy(8, 36));
            locs.add(new LocationCopy(13, 33));//center
            locs.add(new LocationCopy(18, 34));
            locs.add(new LocationCopy(15, 36));//adding a new point because otherwhise it will never be enough for a group greater than 5
    
            return locs;
        }
    
        private static String locToString(Location loc) {
            return loc.getBlockX() + " " + loc.getBlockY() + " " + loc.getBlockZ();
        }
    
        private static double distance(double x1, double x2, double z1, double z2) {
            return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(z2 - z1, 2));
        }
    }
    

    类Location(重要的部分是hashCode方法):

    public class Location {
    
        public int x, y, z;
    
        public Location(int x, int y, int z) {
            this.x = x;
            this.y = y;
            this.z = z;
        }
    
        public int getBlockX() {
            return x;
        }
    
        public int getBlockY() {
            return y;
        }
    
        public int getBlockZ() {
            return z;
        }
    
        @Override
        public String toString() {
            return "Location [x=" + x + ", y=" + y + ", z=" + z + "]";
        }
    
        //EDIT here the hashCode is also important for the HashSets you use in your code
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + x;
            result = prime * result + y;
            result = prime * result + z;
            return result;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Location other = (Location) obj;
            if (x != other.x)
                return false;
            if (y != other.y)
                return false;
            if (z != other.z)
                return false;
            return true;
        }
    }
    

    还有一个用于比较距离的新类 LocationDistance:

    /**
     * A class for comparing the distances for locations
     */
    public class LocationDistance implements Comparable<LocationDistance> {
    
        private Location location;
        private double distance;
    
        public LocationDistance(Location location, double distance) {
            this.location = location;
            this.distance = distance;
        }
    
        @Override
        public String toString() {
            return "LocationDistance [location=" + location + ", distance=" + distance + "]";
        }
    
        @Override
        public int compareTo(LocationDistance other) {
            return Double.compare(distance, other.getDistance());
        }
    
        public Location getLocation() {
            return location;
        }
        public void setLocation(Location location) {
            this.location = location;
        }
    
        public double getDistance() {
            return distance;
        }
        public void setDistance(double distance) {
            this.distance = distance;
        }
    }
    

    输出是:

    More than 6 2 0 0: <br>
    More than 6 1 0 2: <br>
    More than 6 2 0 1: <br>
    More than 6 5 0 0: <br>
    More than 6 4 0 1: <br>
    More than 6 3 0 2: <br>
    More than 6 10 0 30: <br>
    More than 6 12 0 31: <br>
    More than 6 8 0 36: <br>
    More than 6 15 0 31: <br>
    More than 6 13 0 33: <br>
    More than 6 15 0 36: <br>
    More than 6 18 0 34: <br>
    More than 6 0 0 0: <br>
    
    center found: Location [x=2, y=0, z=1]
    center found: Location [x=13, y=0, z=33]
    

    最后两行是您要搜索的中心。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-10
      • 2018-09-08
      • 2010-12-03
      相关资源
      最近更新 更多