java 求最小外接矩形框

https://zhuanlan.zhihu.com/p/97855964

https://blog.csdn.net/staHuri/article/details/87910716

https://github.com/huifer/planar_algorithm


import com.hellobike.aiplatform.base.MPoint;
import lombok.Builder;
import lombok.Data;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class TestMIn {

    @Builder
    @Data
    static class MinRect {
        public List<MPoint> minRect;
        public double area;

        public MinRect(List<MPoint> minRect, double area) {
            this.minRect = minRect;
            this.area = area;
        }
    }

    public static MinRect getMinRect(List<MPoint> points) {
        List<Double> lons = new ArrayList<>();
        List<Double> lats = new ArrayList<>();

        for (MPoint elem : points) {
            lons.add(elem.getLon());
            lats.add(elem.getLat());
        }
        double minlon, minlat, maxlon, maxlat;
        minlon = Collections.min(lons);
        minlat = Collections.min(lats);
        maxlon = Collections.max(lons);
        maxlat = Collections.max(lats);
        MPoint pointa = MPoint.builder().lat(minlat).lon(minlon).build();
        MPoint pointb = MPoint.builder().lat(maxlat).lon(maxlon).build();
        MPoint pointc = MPoint.builder().lat(maxlat).lon(minlon).build();
        MPoint pointd = MPoint.builder().lat(minlat).lon(maxlon).build();
        List<MPoint> minRect = new ArrayList<MPoint>();
        minRect.add(pointa);
        minRect.add(pointb);
        minRect.add(pointc);
        minRect.add(pointd);
        double area = (maxlat - minlat) * (maxlon - minlon);
        return new MinRect(minRect, area);
    }

    public static MPoint getSubtra(MPoint pointa, MPoint pointb) {
        return new MPoint(pointa.getLon() - pointb.getLon(), pointa.getLat() - pointb.getLat());
    }

    public static double computeRad(MPoint vector) {
        double EPS = 1e-10;
        return Math.atan(vector.getLat() / (vector.getLon() + EPS));
    }


    public static List<MPoint> rotate_poly(List<MPoint> points, double rad) {
        double a = Math.cos(rad);
        double b = Math.sin(rad);
        double c = -Math.sin(rad);
        double d = Math.cos(rad);
        List<MPoint> new_points = new ArrayList<>();
        for (MPoint point : points) {
            new_points.add(new MPoint(point.getLon() * a + point.getLat() * c,
                    point.getLon() * b + point.getLat() * d));
        }
        return new_points;
    }

    public static List<MPoint> getPoints(String points_str) {
        List<MPoint> points = new ArrayList<>();
        String[] arr = points_str.split(";");
        for (String elem : arr) {
            String[] point = elem.split(",");
            MPoint newPoint = new MPoint();
            newPoint.setLon(Double.parseDouble(point[0]));
            newPoint.setLat(Double.parseDouble(point[1]));
            points.add(newPoint);
        }
        return points;

    }

    public static List<MPoint> getFinalMinRect(String trace) {

        List<MPoint> points = getPoints(trace);

        /* 计算弧度*/
        int points_count = points.size();
        List<Double> rad = new ArrayList<>();
        rad.add(computeRad(getSubtra(points.get(points_count - 1), points.get(0))));
        for (int i = 1; i <= points_count - 1; i++) {
            rad.add(computeRad(getSubtra(points.get(i - 1), points.get(i))));
        }

        /* 遍历弧度 */
        MinRect oldRectObj = getMinRect(points);
        List<MPoint> rectMin = oldRectObj.getMinRect();
        double areaMin = oldRectObj.getArea();
        double radMin = 0;
        for (double r : rad) {
            List<MPoint> new_points = rotate_poly(points, -r);
            MinRect newRectObj = getMinRect(new_points);
            List<MPoint> rect = newRectObj.getMinRect();
            double area = newRectObj.getArea();
            if (area < areaMin) {
                rectMin = rect;
                areaMin = area;
                radMin = r;
            }
        }
        List<MPoint> finalPoints = rotate_poly(rectMin, radMin);
        System.out.println(areaMin);

        for (MPoint point : finalPoints) {
            System.out.println(point.getLon() + "," + point.getLat());
        }
        return finalPoints;
    }

    public static void main(String[] args) throws Exception {
        String trace = "112.88726,22.565811;112.88726,22.565916;112.88726,22.565998;112.887291,22.566076;112.88736,22.566124;112.887444,22.566147;112.888008,22.56613;112.888588,22.566103;112.88871,22.56608;112.889793,22.566025;112.890701,22.565998;112.890785,22.565989;112.890823,22.56694;112.890854,22.567305;112.890793,22.567345;112.890579,22.567505;112.890198,22.567822;112.889717,22.568256;112.889717,22.568256;112.887787,22.570036;112.886887,22.570869;112.886604,22.571228;112.886383,22.571535;112.886269,22.571762;112.886139,22.572041;112.885994,22.57251;112.885925,22.572779;112.885887,22.573103;112.885818,22.573662;112.885727,22.574732;112.88562,22.57576;112.885544,22.576445;112.885521,22.576849;112.885521,22.576902;112.885468,22.577305;112.885323,22.578629;112.885277,22.579107;112.885239,22.579536;112.885193,22.580017;112.88517,22.58021;112.885162,22.580299;112.885155,22.5804;112.885185,22.580446;112.885147,22.580902;112.885155,22.581093;112.885155,22.581152;112.885193,22.58147;112.885201,22.581697;112.885254,22.582235;112.885254,22.582235;112.885361,22.582413;112.885468,22.582535;112.885635,22.582668;112.885811,22.582668;112.886429,22.582722;112.886871,22.582783;112.887291,22.582861;112.887466,22.582916;112.88784,22.583019;112.888268,22.583168;112.889404,22.583584;112.889404,22.583584;112.889519,22.58359;112.889626,22.583633;112.889679,22.583672;112.889709,22.583719;112.889717,22.583811;112.889709,22.583853;112.889694,22.583893;112.889633,22.583984;112.889587,22.584011;112.889557,22.584026;112.889519,22.584036;112.88945,22.58404;112.88945,22.58404;112.889488,22.584372;112.889496,22.584497;112.889526,22.584627;112.889572,22.584743;112.889694,22.585018;112.889847,22.585226;112.889999,22.585373;112.890053,22.585424;112.890053,22.585424;112.890907,22.586315;112.890907,22.586315;112.891342,22.586794;112.89151,22.586962;112.892403,22.587891;112.892593,22.588099;112.892761,22.588234;112.892914,22.588316;112.89299,22.58835;112.893127,22.588383;112.893227,22.588387;112.893333,22.588377;112.893478,22.588329;112.893517,22.588293;112.893623,22.588215;112.893692,22.588133;112.893715,22.588081;112.893761,22.587973;112.893776,22.587891;112.893784,22.587873;112.893784,22.587812;112.893768,22.587738;112.893753,22.587677;112.8937,22.587564;112.893654,22.587513;112.893593,22.58746;112.893532,22.587418;112.89341,22.587368;112.893318,22.587339;112.893257,22.587339;112.893127,22.587349;112.893028,22.587368;112.892784,22.58746;112.892128,22.587755;112.891937,22.587826;112.891815,22.587891;112.889977,22.588802;112.888039,22.58968;112.887886,22.589745;112.887741,22.589809;112.887741,22.589809;112.886711,22.590313;112.886429,22.590477;112.885902,22.590847;112.885628,22.591076;112.885132,22.591562;112.884903,22.591848;112.884361,22.592623;112.88401,22.593069;112.883812,22.593288;112.883606,22.593464;112.883438,22.593584;112.883308,22.593676;112.882988,22.593838;112.882637,22.593948;112.882256,22.594021;112.881905,22.59403;112.881645,22.594011;112.881508,22.593994;112.881187,22.59392;112.880898,22.593811;112.880615,22.593666;112.880295,22.593443;112.880013,22.593151;112.879875,22.592987;112.879753,22.592773;112.879608,22.592478;112.879501,22.591999;112.879486,22.591612;112.879509,22.591324;112.879562,22.591089;112.879761,22.590588;112.880013,22.590147;112.880447,22.589504;112.880676,22.589081;112.880806,22.588703;112.880875,22.588484;112.880928,22.588234;112.880943,22.587969;112.880943,22.587891;112.880943,22.5877;112.880905,22.58736;112.880783,22.586884;112.880692,22.586649;112.880417,22.586142;112.880241,22.585876;112.880013,22.585577;112.879463,22.584848;112.879486,22.584723;112.879028,22.584171;112.87719,22.581902;112.875847,22.580292;112.874908,22.579262;112.873672,22.578056;112.873528,22.577925;112.872406,22.576902;112.869873,22.57461;112.869102,22.573839;112.868416,22.573103;112.868034,22.572664;112.867798,22.57235;112.86721,22.571503;112.866997,22.571152;112.86631,22.569887;112.866096,22.569395;112.865921,22.568953;112.865623,22.568069;112.865303,22.566708;112.865219,22.566103;112.865211,22.565916;112.865135,22.565001;112.86512,22.563475;112.865097,22.560505;112.865097,22.560122;112.865097,22.55974;112.865059,22.554932;112.865059,22.554508;112.865097,22.553976;112.865128,22.553438;112.865387,22.5518;112.865982,22.549431;112.866081,22.549049;112.866127,22.548758;112.866264,22.547995;112.866348,22.547314;112.866356,22.547205;112.866325,22.546181;112.866196,22.545053;112.865906,22.544022;112.865868,22.543945;112.865555,22.543152;112.864433,22.540825;112.864212,22.540251;112.863922,22.539223;112.863655,22.538181;112.86232,22.532955;112.861893,22.531267;112.861046,22.528103;112.860161,22.52453;112.85968,22.522928;112.859299,22.521971;112.859192,22.521715;112.858101,22.519722;112.857437,22.518803;112.856743,22.517939;112.855682,22.51683;112.855278,22.516445;112.851562,22.513325;112.849236,22.511375;112.848763,22.510984;112.84761,22.510027;112.846313,22.509048;112.845268,22.508398;112.843468,22.507454;112.842232,22.506985;112.841042,22.506601;112.840225,22.50639;112.839745,22.506281;112.838821,22.506042;112.836441,22.505487;112.835159,22.505165;112.834381,22.504955;112.833298,22.50474;112.832726,22.504601;112.829765,22.50388;112.82959,22.503838;112.82872,22.50363;112.826294,22.503046;112.82486,22.502665;112.823357,22.502171;112.821655,22.501471;112.82,22.50066;112.818954,22.5;112.818489,22.499704;112.817749,22.499163;112.816978,22.498507;112.815453,22.497036;112.812729,22.494345;112.809906,22.491575;112.807617,22.489275;112.80735,22.489012;112.805496,22.487144;112.804283,22.48609;112.803558,22.485506;112.802841,22.484922;112.801514,22.484135;112.801201,22.48399;112.800743,22.483793;112.79966,22.483429;112.799042,22.483259;112.797432,22.482996;112.792946,22.482365;112.791817,22.482182;112.787704,22.48164;112.785683,22.481346;112.785645,22.481342;112.784607,22.481146;112.782906,22.480711;112.781731,22.480282;112.78064,22.479773;112.779816,22.479322;112.778923,22.478767;112.777939,22.478024;112.777786,22.477915;112.774033,22.474873;112.770782,22.472319;112.770142,22.471767;112.769478,22.471245;112.768517,22.470482;112.768456,22.470428;112.76683,22.469145;112.765419,22.468069;112.76461,22.467478;112.763977,22.467039;112.763847,22.466957;112.763672,22.466841;112.762909,22.466343;112.761841,22.465712;112.760178,22.464813;112.759384,22.464422;112.758522,22.464022;112.757561,22.463619;112.756073,22.463047;112.755157,22.462729;112.753929,22.462353;112.752403,22.461948;112.751366,22.461706;112.751144,22.461653;112.74987,22.46143;112.748672,22.46122;112.747108,22.461025;112.746628,22.460989;112.744949,22.460842;112.741699,22.46056;112.741295,22.460524;112.734055,22.459927;112.732651,22.459854;112.730904,22.459801;112.728981,22.459778;112.727615,22.459822;112.725403,22.45993;112.723297,22.460091;112.721687,22.460241;112.720917,22.460339;112.719734,22.46051;112.719727,22.46051;112.718071,22.460787;112.7164,22.461067;112.714752,22.461348;112.713982,22.461479;112.710976,22.461981;112.709869,22.462112;112.708664,22.462187;112.707642,22.462227;112.70623,22.462196;112.705437,22.462139;112.704521,22.462044;112.703484,22.461889;112.701599,22.461479;112.700317,22.461121;112.699928,22.460993;112.698952,22.460629;112.697754,22.460133;112.697678,22.460104;112.696587,22.459595;112.695999,22.459284;112.694504,22.458406;112.691483,22.456425;112.69091,22.456055;112.689697,22.455273;112.689301,22.455013;112.688904,22.454744;112.685432,22.452496;112.679901,22.448912;112.679131,22.448406;112.675797,22.446224;112.675781,22.446215;112.673973,22.445065;112.673721,22.444904;112.672157,22.443876;112.67131,22.443293;112.668442,22.441521;112.66745,22.440924;112.666107,22.440191;112.664284,22.439302;112.66391,22.439148;112.66391,22.439148;112.663773,22.439131;112.663132,22.438885;112.662704,22.438763;112.662468,22.438711;112.662331,22.438688;112.662094,22.438681;112.661957,22.438694;112.661835,22.438711;112.661682,22.438742;112.661484,22.438803;112.660927,22.439007;112.66082,22.439032;112.660606,22.439058;112.660393,22.439053;112.660263,22.439032;112.660072,22.438971;112.659988,22.438938;112.659866,22.438862;112.659698,22.438734;112.659592,22.438606;112.659531,22.438528;112.659454,22.438374;112.659416,22.438232;112.659393,22.438143;112.659378,22.438042;112.659378,22.437891;112.659378,22.437847;112.659401,22.4377;112.659485,22.43749;112.659554,22.437368;112.65992,22.436876;112.659988,22.436745;112.66008,22.436548;112.660126,22.436367;112.660133,22.436224;112.660141,22.436075;112.660126,22.435989;112.660088,22.435806;112.660011,22.43561;112.659843,22.435373;112.659149,22.434601;112.658623,22.43412;112.658585,22.43408;112.65831,22.433762;112.65831,22.433762;112.657341,22.432465;112.656372,22.430994;112.65609,22.43046;112.65551,22.429285;112.655487,22.429213;112.655281,22.428759;112.654961,22.427896;112.654915,22.427752;112.654625,22.426767;112.654434,22.42605;112.654243,22.425032;112.654167,22.424576;112.654045,22.423801;112.653923,22.423096;112.653877,22.422756;112.653824,22.422445;112.653801,22.422344;112.653336,22.419271;112.65303,22.417173;112.652916,22.415911;112.652908,22.415251;112.652916,22.415192;112.652962,22.414375;112.653061,22.413651;112.653168,22.41312;112.653297,22.412626;112.653442,22.412188;112.653465,22.412109;112.653656,22.411627;112.653801,22.411263;112.654053,22.410738;112.654587,22.409704;112.656509,22.406202;112.659317,22.401119;112.659386,22.40098;112.659935,22.399935;112.660202,22.399345;112.660385,22.398911;112.660606,22.398256;112.660713,22.397892;112.660851,22.397278;112.660942,22.396723;112.661003,22.396219;112.661034,22.395628;112.661034,22.39525;112.660995,22.394527;112.660957,22.394119;112.660667,22.391884;112.660423,22.390156;112.660423,22.390133;112.660301,22.389158;112.660225,22.38843;112.660194,22.387659;112.660194,22.387096;112.660225,22.386425;112.660873,22.380764;112.660904,22.380447;112.660957,22.380013;112.660995,22.379858;112.661194,22.379713;112.661865,22.379614;112.662491,22.379488;112.664101,22.379213;112.664673,22.379148;112.665077,22.379124;112.665619,22.379107;112.666016,22.379116;112.666306,22.379124;112.666611,22.379148;112.666809,22.379162;112.666901,22.379175;112.667389,22.37924;112.668739,22.379467;112.669891,22.379641;112.67086,22.379753;112.671875,22.379805;112.672615,22.379814;112.673393,22.379805;112.674194,22.379787;112.675262,22.379768;112.675781,22.379763;112.676498,22.379749;112.678085,22.379723;112.678749,22.379713;112.67881,22.379704;112.679428,22.379696;112.680153,22.379681;112.680954,22.379675;112.681198,22.379675;112.68174,22.37991;112.681656,22.380127;112.681564,22.380342;112.681335,22.380964;112.681145,22.381466;112.681038,22.381762;112.681038,22.381762;112.681175,22.381844;112.681175,22.381844;112.681229,22.381857;112.681435,22.381905;112.681747,22.382;112.681839,22.382;112.68232,22.382017;112.682426,22.381996;112.68251,22.38199;112.68251,22.38199;112.682594,22.381784;112.682632,22.381716";
        getFinalMinRect(trace);

    }
发布了59 篇原创文章 · 获赞 11 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/u013385018/article/details/103976869