精华内容
下载资源
问答
  • 判断一个点是否在某个区域内(多边形) 比如滴滴会根据乘客所在的不同区域,给出不同的价格。市区堵一点,那么价格也高点。获取服务范围只规定在某个范围

    判断一个点是否在某个区域内(多边形)

    背景:

        比如滴滴会根据乘客所在的不同区域,给出不同的价格。市区堵一点,那么价格也高点。获取服务范围只规定在某个范围内

    原理:

        求解从该点向右发出的水平线射线与多边形各边的交点,当交点数为奇数,则在内部。

        不过要注意几种特殊情况:1、点在边或者顶点上;2、点在边的延长线上;3、点出发的水平射线与多边形相交在顶点上

        

    源代码:

        Point类-多边形顶点的封装类如坐标(166.3,18.4)
        Line类-多边形对应的各个边的封装类,如{(166.3,18.4), (166.9,19)}
        MapUtil类-地图公共处理类

        

    package com.qj.book.util;
    
    
        /**
         * Created by xsm48563 on 2017/10/31.
         * 点
         */
        public class Point {
    
    
            /**
             * 水平方向值/经度
             */
            public Double X;
            /**
             * 垂直方向值/纬度
             */
            public Double Y;
    
    
            Point(Double x, Double y) {
    
    
                x = x == null ? 0:x;
                y = y == null ? 0:y;
                this.X = x;
                this.Y = y;
            }
    
    
            public boolean equals(Object obj) {
    
    
                // 如果为同一对象的不同引用,则相同
                if (this == obj) {
                    return true;
                }
                // 如果传入的对象为空,则返回false
                if (obj == null) {
                    return false;
                }
                if (obj instanceof Point) {
                    Point point = (Point) obj;
                    if (point.X.equals(this.X) && point.Y.equals(this.Y)) {
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            }
    
    
            public static void main(String[] args) {
    
    
                Point A = new Point(1d, null);
                Point B = new Point(null, 3d);
                System.out.println(A.equals(B));
            }
        }
    
    
        package com.qj.book.util;
    
    
        import java.math.BigDecimal;
    
    
        /**
         * Created by xsm48563 on 2017/10/31.
         * 线
         */
        public class Line {
    
    
            /**
             * 端点1
             */
            public Point POINTA;
    
    
            /**
             * 端点2
             */
            public Point POINTB;
    
    
            Line(Point pointA, Point pointB) {
    
    
                this.POINTA = pointA;
                this.POINTB = pointB;
            }
    
    
            /**
             * 判断当前线段是否包含给定的点</br>
             * 即给定的点是否在当前边上
             * @param point
             * @return
             */
            public boolean isContainsPoint(Point point) {
    
    
                boolean result = false;
                //判断给定点point与端点1构成线段的斜率是否和当前线段的斜率相同
                //给定点point与端点1构成线段的斜率k1
                Double k1 = null;
                if (point.X.equals(this.POINTA.X)) {
                    k1 = Double.NEGATIVE_INFINITY;
                } else {
                    k1 = div(sub(point.Y, this.POINTA.Y), sub(point.X, this.POINTA.X));
                }
                //当前线段的斜率k2
                Double k2 = null;
                if (this.POINTB.X.equals(this.POINTA.X)) {
                    k2 = Double.NEGATIVE_INFINITY;
                } else {
                    k2 = div(sub(this.POINTB.Y, this.POINTA.Y), sub(this.POINTB.X, this.POINTA.X));
                }
                if (k1 != null && k2 != null) {
                    if (k1.equals(k2)) {
                        //若斜率相同,继续判断给定点point的x是否在pointA.x和pointB.x之间,若在 则说明该点在当前边上
                        if (sub(point.X, this.POINTA.X) * sub(point.X, this.POINTB.X) < 0) {
                            result = true;
                        }
                    }
                }
                return result;
            }
    
    
            //叉积
            double mult(Point a, Point b, Point c) {
                return (a.X-c.X)*(b.Y-c.Y)-(b.X-c.X)*(a.Y-c.Y);
            }
    
    
            /**
             * 给定线段是否与当前线段相交</br>
             * 相交返回true, 不相交返回false
             * @param line
             * @return
             */
            public boolean
            isIntersect(Line line) {
    
    
                Point aa = this.POINTA;
                Point bb = this.POINTB;
                Point cc = line.POINTA;
                Point dd = line.POINTB;
                if (Math.max(aa.X, bb.X) < Math.min(cc.X, dd.X)) {
                    return false;
                }
                if (Math.max(aa.Y, bb.Y) < Math.min(cc.Y, dd.Y)) {
                    return false;
                }
                if (Math.max(cc.X, dd.X) < Math.min(aa.X, bb.X)) {
                    return false;
                }
                if (Math.max(cc.Y, dd.Y) < Math.min(aa.Y, bb.Y)) {
                    return false;
                }
                if (mult(cc, bb, aa) * mult(bb, dd, aa) < 0 ) {
                    return false;
                }
                if ( mult(aa, dd, cc) * mult(dd, bb, cc) < 0 ) {
                    return false;
                }
                return true;
            }
    
    
            /**
             * 提供精确的加法运算。
             * @param v1 被加数
             * @param v2 加数
             * @return 两个参数的和
             */
            public static double add(double v1,double v2){
                BigDecimal b1 = new BigDecimal(Double.toString(v1));
                BigDecimal b2 = new BigDecimal(Double.toString(v2));
                return b1.add(b2).doubleValue();
            }
    
    
            /**
             * 提供精确的减法运算。
             * @param v1 被减数
             * @param v2 减数
             * @return 两个参数的差
             */
            public static double sub(double v1,double v2){
                BigDecimal b1 = new BigDecimal(Double.toString(v1));
                BigDecimal b2 = new BigDecimal(Double.toString(v2));
                return b1.subtract(b2).doubleValue();
            }
    
    
            /**
             * 提供精确的乘法运算。
             * @param v1 被乘数
             * @param v2 乘数
             * @return 两个参数的积
             */
            public static double mul(double v1,double v2){
                BigDecimal b1 = new BigDecimal(Double.toString(v1));
                BigDecimal b2 = new BigDecimal(Double.toString(v2));
                return b1.multiply(b2).doubleValue();
            }
    
    
            private static final int DEF_DIV_SCALE = 10;
    
    
            /**
             * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
             * 小数点以后10位,以后的数字四舍五入。
             * @param v1 被除数
             * @param v2 除数
             * @return 两个参数的商
             */
            public static double div(double v1,double v2){
                return div(v1,v2,DEF_DIV_SCALE);
            }
    
    
            /**
             * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
             * 定精度,以后的数字四舍五入。
             * @param v1 被除数
             * @param v2 除数
             * @param scale 表示表示需要精确到小数点以后几位。
             * @return 两个参数的商
             */
            public static double div(double v1,double v2,int scale){
                if(scale<0){
                    throw new IllegalArgumentException(
                            "The scale must be a positive integer or zero");
                }
                BigDecimal b1 = new BigDecimal(Double.toString(v1));
                BigDecimal b2 = new BigDecimal(Double.toString(v2));
                return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
            }
        }
    
    
        package com.qj.book.util;
    
    
        import com.alibaba.fastjson.JSONArray;
        import com.alibaba.fastjson.JSONObject;
        import java.math.BigDecimal;
        import java.util.ArrayList;
        import java.util.List;
    
    
        /**
         * Created by xsm48563 on 2017/10/31.
         * 图形专用类
         */
        public class MapUtil {
    
    
    
    
            /**
             * 给定点和多边形,判断给定的点是否在多边形内
             * @param point
             * @param points
             * @return
             */
            public static boolean isPointInPolygon(Point point, List<Point> points) {
    
    
                boolean result = false;
                int intersectCount = 0;
                // 判断依据:求解从该点向右发出的水平线射线与多边形各边的交点,当交点数为奇数,则在内部
                //不过要注意几种特殊情况:1、点在边或者顶点上;2、点在边的延长线上;3、点出发的水平射线与多边形相交在顶点上
                /**
                 * 具体步骤如下:
                 * 循环遍历各个线段:
                 *  1、判断点是否在当前边上(斜率相同,且该点的x值在两个端口的x值之间),若是则返回true
                 *  2、否则判断由该点发出的水平射线是否与当前边相交,若不相交则continue
                 *  3、若相交,则判断是否相交在顶点上(边的端点是否在给定点的水平右侧).若不在,则认为此次相交为穿越,交点数+1 并continue
                 *  4、若交在顶点上,则判断上一条边的另外一个端点与当前边的另外一个端点是否分布在水平射线的两侧.若是则认为此次相交为穿越,交点数+1.
                 */
                for (int i = 0; i < points.size(); i++) {
                    Point pointA = points.get(i);
                    Point pointB = null;
                    Point pointPre = null;
                    //若当前是第一个点,则上一点则是list里面的最后一个点
                    if (i == 0) {
                        pointPre = points.get(points.size() - 1);
                    } else {
                        pointPre = points.get(i - 1);
                    }
                    //若已经循环到最后一个点,则与之连接的是第一个点
                    if (i == (points.size() - 1)) {
                        pointB = points.get(0);
                    } else {
                        pointB = points.get(i + 1);
                    }
                    Line line = new Line(pointA, pointB);
                    //1、判断点是否在当前边上(斜率相同,且该点的x值在两个端口的x值之间),若是则返回true
                    boolean isAtLine = line.isContainsPoint(point);
                    if (isAtLine) {
                        return true;
                    } else {
                        //2、若不在边上,判断由该点发出的水平射线是否与当前边相交,若不相交则continue
                        //设置该射线的另外一个端点的x值=999,保证边的x永远不超过
                        Point  radialPoint = new Point(999d, point.Y);
                        Line radial = new Line(point, radialPoint);
                        boolean isIntersect = radial.isIntersect(line);
                        if (!isIntersect) {
                            continue;
                        } else {
                            //3、若相交,则判断是否相交在顶点上(边的端点是否在给定点的水平右侧).若不在,则认为此次相交为穿越,交点数+1 并continue
                            if (!( (pointA.X > point.X) && (pointA.Y.equals(point.Y))
                                    || (pointB.X > point.X) && (pointB.Y.equals(point.Y)) )) {
                                intersectCount++;
                                continue;
                            } else {
                                //4、若交在顶点上,则判断上一条边的另外一个端点与当前边的另外一个端点是否分布在水平射线的两侧.若是则认为此次相交为穿越,交点数+1
                                if ((pointPre.Y - point.Y) * (pointB.Y - point.Y) < 0) {
                                    intersectCount++;
                                }
                            }
                        }
                    }
                }
                result = intersectCount % 2 == 1;
                return result;
            }
    
    
            public static void main(String[] args) {
    
    
                Point point11 = new Point(1d, 2d);
                Point point22 = new Point(2d, 4d);
                Point point33 = new Point(3d, 4d);
                Point point44 = new Point(5d, 2d);
                Point point55 = new Point(5d, 1d);
                Point point66 = new Point(3d, 0d);
                List<Point> points = new ArrayList<>();
                points.add(point11);
                points.add(point22);
                points.add(point33);
                points.add(point44);
                points.add(point55);
                points.add(point66);
                Point test = new Point(2d, 3d);
                System.out.println(isPointInPolygon(test, points));
            }
        }

    转载至:http://www.qunjianinfo.com/com/qj/front/content.html?fmId=28&catalogNo=2


    展开全文
  • 我想在手机网页上实现在一个固定的区域内有一个div,这个div能够随着手指的滑动而改变位置,求各位大神指点迷津。。
  • 判断触摸事件是否在View指定区域内 用此方法来完成点击自定义View中某个区域才实现什么功能。 **使用 Rect.contains(float, float) 判断触摸事件是否在 View 内: ** 方法:boolean isInViewRect = rectf.contains...

    判断触摸事件是否在View指定区域内


    用此方法来完成点击自定义View中某个区域才实现什么功能。
    **使用 Rect.contains(float, float) 判断触摸事件是否在 View 内: **
    方法:boolean isInViewRect = rectf.contains(x, y);

    override fun onTouchEvent(event: MotionEvent): Boolean {
            if (event.action == MotionEvent.ACTION_DOWN) {
                mClickStartFlag = mRects[8].contains(event.x, event.y)
                Log.e("event","${event.x}+${event.y}")
                Log.e("event","${mRects[8]}")
                return true
            }
            if (event.action == MotionEvent.ACTION_UP) {
                if (mClickStartFlag) {
                    if (mRects[8].contains(event.x, event.y)) {
                        starAnim() //判断只有手指落下和抬起都在中间的矩形内才开始动画
                    }
                    mClickStartFlag = false
                }
            }
            return super.onTouchEvent(event)
        }
    

    在这里插入图片描述

    展开全文
  • 判断一个点是否在某个区域内(多边形)背景:比如滴滴会根据乘客所在的不同区域,给出不同的价格。市区堵一点,那么价格也高点。获取服务范围只规定在某个范围内原理:求解从该点向右发出的水平线射线与多边形各边的...
     判断一个点是否在某个区域内(多边形)

    背景:
    比如滴滴会根据乘客所在的不同区域,给出不同的价格。市区堵一点,那么价格也高点。获取服务范围只规定在某个范围内

    原理:
    求解从该点向右发出的水平线射线与多边形各边的交点,当交点数为奇数,则在内部。
    不过要注意几种特殊情况:1、点在边或者顶点上;2、点在边的延长线上;3、点出发的水平射线与多边形相交在顶点上

    源代码:
    Point类-多边形顶点的封装类如坐标(166.3,18.4)
    Line类-多边形对应的各个边的封装类,如{(166.3,18.4), (166.9,19)}
    MapUtil类-地图公共处理类

    package com.qj.book.util;

    /**
    * Created by xsm48563 on 2017/10/31.
    * 点
    */
    public class Point {

    /**
    * 水平方向值/经度
    */
    public Double X;
    /**
    * 垂直方向值/纬度
    */
    public Double Y;

    Point(Double x, Double y) {

    x = x == null ? 0:x;
    y = y == null ? 0:y;
    this.X = x;
    this.Y = y;
    }

    public boolean equals(Object obj) {

    // 如果为同一对象的不同引用,则相同
    if (this == obj) {
    return true;
    }
    // 如果传入的对象为空,则返回false
    if (obj == null) {
    return false;
    }
    if (obj instanceof Point) {
    Point point = (Point) obj;
    if (point.X.equals(this.X) && point.Y.equals(this.Y)) {
    return true;
    } else {
    return false;
    }
    } else {
    return false;
    }
    }

    public static void main(String[] args) {

    Point A = new Point(1d, null);
    Point B = new Point(null, 3d);
    System.out.println(A.equals(B));
    }
    }

    package com.qj.book.util;

    import java.math.BigDecimal;

    /**
    * Created by xsm48563 on 2017/10/31.
    * 线
    */
    public class Line {

    /**
    * 端点1
    */
    public Point POINTA;

    /**
    * 端点2
    */
    public Point POINTB;

    Line(Point pointA, Point pointB) {

    this.POINTA = pointA;
    this.POINTB = pointB;
    }

    /**
    * 判断当前线段是否包含给定的点

    * 即给定的点是否在当前边上
    * @param point
    * @return
    */
    public boolean isContainsPoint(Point point) {

    boolean result = false;
    //判断给定点point与端点1构成线段的斜率是否和当前线段的斜率相同
    //给定点point与端点1构成线段的斜率k1
    Double k1 = null;
    if (point.X.equals(this.POINTA.X)) {
    k1 = Double.NEGATIVE_INFINITY;
    } else {
    k1 = div(sub(point.Y, this.POINTA.Y), sub(point.X, this.POINTA.X));
    }
    //当前线段的斜率k2
    Double k2 = null;
    if (this.POINTB.X.equals(this.POINTA.X)) {
    k2 = Double.NEGATIVE_INFINITY;
    } else {
    k2 = div(sub(this.POINTB.Y, this.POINTA.Y), sub(this.POINTB.X, this.POINTA.X));
    }
    if (k1 != null && k2 != null) {
    if (k1.equals(k2)) {
    //若斜率相同,继续判断给定点point的x是否在pointA.x和pointB.x之间,若在 则说明该点在当前边上
    if (sub(point.X, this.POINTA.X) * sub(point.X, this.POINTB.X) < 0) {
    result = true;
    }
    }
    }
    return result;
    }

    //叉积
    double mult(Point a, Point b, Point c) {
    return (a.X-c.X)*(b.Y-c.Y)-(b.X-c.X)*(a.Y-c.Y);
    }

    /**
    * 给定线段是否与当前线段相交

    * 相交返回true, 不相交返回false
    * @param line
    * @return
    */
    public boolean
    isIntersect(Line line) {

    Point aa = this.POINTA;
    Point bb = this.POINTB;
    Point cc = line.POINTA;
    Point dd = line.POINTB;
    if (Math.max(aa.X, bb.X) < Math.min(cc.X, dd.X)) {
    return false;
    }
    if (Math.max(aa.Y, bb.Y) < Math.min(cc.Y, dd.Y)) {
    return false;
    }
    if (Math.max(cc.X, dd.X) < Math.min(aa.X, bb.X)) {
    return false;
    }
    if (Math.max(cc.Y, dd.Y) < Math.min(aa.Y, bb.Y)) {
    return false;
    }
    if (mult(cc, bb, aa) * mult(bb, dd, aa) < 0 ) {
    return false;
    }
    if ( mult(aa, dd, cc) * mult(dd, bb, cc) < 0 ) {
    return false;
    }
    return true;
    }

    /**
    * 提供精确的加法运算。
    * @param v1 被加数
    * @param v2 加数
    * @return 两个参数的和
    */
    public static double add(double v1,double v2){
    BigDecimal b1 = new BigDecimal(Double.toString(v1));
    BigDecimal b2 = new BigDecimal(Double.toString(v2));
    return b1.add(b2).doubleValue();
    }

    /**
    * 提供精确的减法运算。
    * @param v1 被减数
    * @param v2 减数
    * @return 两个参数的差
    */
    public static double sub(double v1,double v2){
    BigDecimal b1 = new BigDecimal(Double.toString(v1));
    BigDecimal b2 = new BigDecimal(Double.toString(v2));
    return b1.subtract(b2).doubleValue();
    }

    /**
    * 提供精确的乘法运算。
    * @param v1 被乘数
    * @param v2 乘数
    * @return 两个参数的积
    */
    public static double mul(double v1,double v2){
    BigDecimal b1 = new BigDecimal(Double.toString(v1));
    BigDecimal b2 = new BigDecimal(Double.toString(v2));
    return b1.multiply(b2).doubleValue();
    }

    private static final int DEF_DIV_SCALE = 10;

    /**
    * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
    * 小数点以后10位,以后的数字四舍五入。
    * @param v1 被除数
    * @param v2 除数
    * @return 两个参数的商
    */
    public static double div(double v1,double v2){
    return div(v1,v2,DEF_DIV_SCALE);
    }

    /**
    * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
    * 定精度,以后的数字四舍五入。
    * @param v1 被除数
    * @param v2 除数
    * @param scale 表示表示需要精确到小数点以后几位。
    * @return 两个参数的商
    */
    public static double div(double v1,double v2,int scale){
    if(scale<0){
    throw new IllegalArgumentException(
    "The scale must be a positive integer or zero");
    }
    BigDecimal b1 = new BigDecimal(Double.toString(v1));
    BigDecimal b2 = new BigDecimal(Double.toString(v2));
    return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
    }
    }

    package com.qj.book.util;

    import com.alibaba.fastjson.JSONArray;
    import com.alibaba.fastjson.JSONObject;
    import java.math.BigDecimal;
    import java.util.ArrayList;
    import java.util.List;

    /**
    * Created by xsm48563 on 2017/10/31.
    * 图形专用类
    */
    public class MapUtil {


    /**
    * 给定点和多边形,判断给定的点是否在多边形内
    * @param point
    * @param points
    * @return
    */
    public static boolean isPointInPolygon(Point point, Listpoints) {

    boolean result = false;
    int intersectCount = 0;
    // 判断依据:求解从该点向右发出的水平线射线与多边形各边的交点,当交点数为奇数,则在内部
    //不过要注意几种特殊情况:1、点在边或者顶点上;2、点在边的延长线上;3、点出发的水平射线与多边形相交在顶点上
    /**
    * 具体步骤如下:
    * 循环遍历各个线段:
    * 1、判断点是否在当前边上(斜率相同,且该点的x值在两个端口的x值之间),若是则返回true
    * 2、否则判断由该点发出的水平射线是否与当前边相交,若不相交则continue
    * 3、若相交,则判断是否相交在顶点上(边的端点是否在给定点的水平右侧).若不在,则认为此次相交为穿越,交点数+1 并continue
    * 4、若交在顶点上,则判断上一条边的另外一个端点与当前边的另外一个端点是否分布在水平射线的两侧.若是则认为此次相交为穿越,交点数+1.
    */
    for (int i = 0; i < points.size(); i++) {
    Point pointA = points.get(i);
    Point pointB = null;
    Point pointPre = null;
    //若当前是第一个点,则上一点则是list里面的最后一个点
    if (i == 0) {
    pointPre = points.get(points.size() - 1);
    } else {
    pointPre = points.get(i - 1);
    }
    //若已经循环到最后一个点,则与之连接的是第一个点
    if (i == (points.size() - 1)) {
    pointB = points.get(0);
    } else {
    pointB = points.get(i + 1);
    }
    Line line = new Line(pointA, pointB);
    //1、判断点是否在当前边上(斜率相同,且该点的x值在两个端口的x值之间),若是则返回true
    boolean isAtLine = line.isContainsPoint(point);
    if (isAtLine) {
    return true;
    } else {
    //2、若不在边上,判断由该点发出的水平射线是否与当前边相交,若不相交则continue
    //设置该射线的另外一个端点的x值=999,保证边的x永远不超过
    Point radialPoint = new Point(999d, point.Y);
    Line radial = new Line(point, radialPoint);
    boolean isIntersect = radial.isIntersect(line);
    if (!isIntersect) {
    continue;
    } else {
    //3、若相交,则判断是否相交在顶点上(边的端点是否在给定点的水平右侧).若不在,则认为此次相交为穿越,交点数+1 并continue
    if (!( (pointA.X > point.X) && (pointA.Y.equals(point.Y))
    || (pointB.X > point.X) && (pointB.Y.equals(point.Y)) )) {
    intersectCount++;
    continue;
    } else {
    //4、若交在顶点上,则判断上一条边的另外一个端点与当前边的另外一个端点是否分布在水平射线的两侧.若是则认为此次相交为穿越,交点数+1
    if ((pointPre.Y - point.Y) * (pointB.Y - point.Y) < 0) {
    intersectCount++;
    }
    }
    }
    }
    }
    result = intersectCount % 2 == 1;
    return result;
    }

    public static void main(String[] args) {

    Point point11 = new Point(1d, 2d);
    Point point22 = new Point(2d, 4d);
    Point point33 = new Point(3d, 4d);
    Point point44 = new Point(5d, 2d);
    Point point55 = new Point(5d, 1d);
    Point point66 = new Point(3d, 0d);
    List points = new ArrayList<>();
    points.add(point11);
    points.add(point22);
    points.add(point33);
    points.add(point44);
    points.add(point55);
    points.add(point66);
    Point test = new Point(2d, 3d);
    System.out.println(isPointInPolygon(test, points));
    }

    }




    在做LBS,POI相关项目时,经常需要判断一个点是否在某个区域中的问题。在实际场景中,这个区域肯定是没有任何规律的不规则形状。针对这种场景,搜索了几种对应的解法。重点是,最后给大家奉上能工作的源码!有需要的同学们千万不能错过。

    1.射线法,PNPoly算法

    本算法是由W. Randolph Franklin提出的。算法的思路如下: 
    从待测点出发作一条射线,可沿y轴方向也可没x轴方向,然后判断这条射线与不规则区域的交点数量。如果点的两边交点的个数都是奇数个则该点在多边形内,否则在多边形外。 
    这个算法对于任意不规则图形都适用。 
    关于本算法更详细的介绍,请参考参考文献1。

    2.多边形面积算法

    非凹多边形,凹多边形需要切割为凸多边形。 
    第四点分别与三角形的两个点组成的面积分别设为S1,S2,S3,只要S1+S2+S3>原来的三角形面积就不在三角形范围中.可以使用海伦公式 。

    3.可用的解决方案

    重点来了….. 
    在实际的项目过程中,不管多精巧的算法,实现功能完成项目是第一位的。算法再好,还得自己去实现去测试,尤其是各种边界条件测试,绝对是要吐血。所以,不管什么算法,啥也不说了,先上代码。

    import java.awt.geom.GeneralPath;
    import java.awt.geom.Point2D;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Created by wanglei on 17-2-14.
     */
    public class MapTools {
    
        public static List genPointList() {
            List list = new ArrayList();
            Point2D.Double p1 = new Point2D.Double(0.0,0.0);
            Point2D.Double p2 = new Point2D.Double(0.0,0.5);
            Point2D.Double p3 = new Point2D.Double(0.0,1.0);
            Point2D.Double p4 = new Point2D.Double(1.0,0.5);
            Point2D.Double p5 = new Point2D.Double(1.0,1.0);
            Point2D.Double p6 = new Point2D.Double(1.0,0.5);
            Point2D.Double p7 = new Point2D.Double(1.0,0.0);
            Point2D.Double p8 = new Point2D.Double(0.5,0.0);
    
            Point2D.Double[] points = {p1,p2,p3,p4,p5,p6,p7,p8};
            for (int i = 0; i < points.length; i++) {
                list.add(points[i]);
            }
    
            return list;
        }
    
        public static boolean checkWithPath(Point2D.Double point, List<Point2D.Double> polygon) {
            GeneralPath p = new GeneralPath();
            Point2D.Double first = polygon.get(0);
            p.moveTo(first.x,first.y);
            for(Point2D.Double d: polygon) {
                p.lineTo(d.x,d.y);
            }
            p.lineTo(first.x,first.y);
            p.closePath();
            return p.contains(point);
        }
    
        public static void main(String[] args) {
            List list = genPointList();
            Point2D.Double p1 = new Point2D.Double(1.5,1.5);
            Point2D.Double p2 = new Point2D.Double(0.2,0.3);
            Point2D.Double p3 = new Point2D.Double(1.5,0.1);
            Point2D.Double p4 = new Point2D.Double(0.8,0.0);
            Point2D.Double p5 = new Point2D.Double(0.08,0.01);
            List<Point2D.Double> testList = new ArrayList();
            testList.add(p1);
            testList.add(p2);
            testList.add(p3);
            testList.add(p4);
            testList.add(p5);
            for(Point2D.Double each:testList) {
                boolean flag = checkWithPath(each,list);
                System.out.println(each.toString() + " is in polygon: " + flag);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    上面的代码主要是用到了java.awt.geom包。java.awt.geom是jdk自带的类包,不用任何额外的安装。GeneralPath 类表示根据直线、二次曲线和三次 (Bézier) 曲线构造的几何路径。它可以包含多个子路径。GeneralPath继承自java.awt.geom.Path2D。那么这个Path2D是干嘛的呢?看看jdk里面的一段注解:

    /**
     * The {@code Path2D} class provides a simple, yet flexible
     * shape which represents an arbitrary geometric path.
     * It can fully represent any path which can be iterated by the
     * {@link PathIterator} interface including all of its segment
     * types and winding rules and it implements all of the
     * basic hit testing methods of the {@link Shape} interface.
     * <p>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    第一句话就告诉了我们Path2D是干嘛的:Path2D类提供了一个简单,灵活的形状类,用来表示任意几何路径。

    测试代码中,生成了一个边长为1的正方形矩形区域,其中一个顶点为(0,0)。最后的测试结果为:

    Point2D.Double[1.5, 1.5] is in polygon: false
    Point2D.Double[0.2, 0.3] is in polygon: true
    Point2D.Double[1.5, 0.1] is in polygon: false
    Point2D.Double[0.8, 0.0] is in polygon: true
    Point2D.Double[0.08, 0.01] is in polygon: true
    • 1
    • 2
    • 3
    • 4
    • 5

    测试结果准确无误,完美地满足了我们的需求! 
    时间关系,没有来得及具体研究jdk里源码的实现细节,后续可以进一步研究Path2D的实现算法。

    参考文档: 
    1.http://blog.csdn.net/hjh2005/article/details/9246967 
    2.http://www.apihome.cn/api/java/GeneralPath.html 
    3.jdk源码


    展开全文
  • android判断点击位置在一扇形区域内

    千次阅读 2017-07-15 17:01:42
    android 判断点击位置在一扇形区域内在做仿支付宝记账本界面效果时遇到了一个问题,在环形图中点击每一个环是会显示出不同的内容,...绘制扇形要判断点击的位置是否是在扇形区域内,首先要绘制扇形,绘制扇形的方法可以

    android 判断点击位置在一扇形区域内

    在做仿支付宝记账本界面效果时遇到了一个问题,在环形图中点击每一个环是会显示出不同的内容,因此,必须判断用户到底点击了哪个圆环,网上查阅资料说可以根据颜色来判断,但是心里总是觉得根据颜色不是很好的解决方案(虽然可以解决这个问题),因此记录下自己解决次问题的方法,也有助于自己后续复习。

    绘制扇形

    要判断点击的位置是否是在扇形区域内,首先要绘制扇形,绘制扇形的方法可以使用canvas.drawArc()方法。这里介绍的是使用Path的方法,然后调用canvas.drawPath(ovalPath,paint);方法来进行绘制。

    主要代码如下:

    @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            //将画布的坐标原点移到圆心位置
            canvas.translate((getWidth() + getPaddingLeft() - getPaddingRight()) / 2,
                    (getHeight() + getPaddingTop() - getPaddingBottom()) / 2);
    
            ovalPath.moveTo(0, 0);
            ovalPath.lineTo(100, 0);
            RectF oval = new RectF(-100,-100,100,100);
            ovalPath.addArc(oval, 0, 160);
            ovalPath.lineTo(0, 0);
            ovalPath.close();
            RectF r = new RectF();
            ovalPath.computeBounds(r, true);
            mRegion.setPath(ovalPath, new Region((int)r.left, (int) r.top, (int) r.right,(int)r.bottom));
            Paint paint = new Paint();
            paint.setColor(Color.RED);
            paint.setAntiAlias(true);
            paint.setStrokeWidth(1);
            paint.setStyle(Paint.Style.STROKE);
            canvas.drawPath(ovalPath,paint);
            mCenterCircleX = (getWidth() + getPaddingLeft() - getPaddingRight()) / 2;
            mCenterCircleY = (getHeight() + getPaddingTop() - getPaddingBottom()) / 2;
    
        }

    获取点击位置,判断是否在扇形内的方法如下:

       public boolean onTouchEvent(MotionEvent event) {
            float x;
            float y;
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    x = event.getX()-mCenterCircleX;
                    y = event.getY()-mCenterCircleY;
                    boolean b = mRegion.contains((int) x, (int) y);
                    Log.d(TAG, "onTouchEvent: b: "+b +" x: "+ x+"  y: "+y);
                    break;
    
            }
            return true;
        }

    这里要注意的是:获取点击位置后,要减去坐标的偏移量,否则将得不到正确的结果。

    扇形效果图日志

    展开全文
  • 所以在布局上搞一个帧布局,下面市地图,上面是一个透明的button,没有画区域时 是GON的,点击画区域按钮后设置为可见, 这样你在这个button上画,就可以通过ontouch方法来得到一系列的屏幕上的点,通过projection 把这
  • 前端开发中,有时需要判断某个元素是否在浏览器的可视区域内,或者是否已经滚动出了可视区域.首先想到的便是javascript操作,原生方法自然可以,不过Jquery已经封装了一些属性,使用起来更方便些,我们这里就讨论这种...
  • 一、背景: 如何判断一个指定的经纬度点是否落在一个多边形区域内?二、实现代码(delphi) CodeCode highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->Type ...
  • 判断指定的经纬度坐标点是否落在指定的多边形区域内 @param ALon 定点的经度 @param ALat 定点的纬度 @param APoints 指定多边形区域各个节点坐标 @return True 落在范围内 False 不在范围内 -------------...
  • 在 CSS 中,width 和 height 的是内容区域的宽度和高度。增加边距、边框和外边距不会影响内容区域的尺寸,但是会增加元素框的总尺寸。
  • Offer——网易校招推笔试题+模拟题知识点总结前言 2016.8.2 19:00网易校招推笔试开始进行。前天晚上利用大约1小时时间完成了测评(这个必须做,关切到你能否参与面试)。上午利用2小时时间做了下模拟题,模拟...
  • 问题:“当我们按下电源开关时,电源开始供电,芯片组撤去RESET信号,CPU马上就从地址FFFF0H处开始执行指令,这个地址在系统BIOS的地址范围内,无论是Award BIOS还是AMI BIOS,放在这里的只是一条跳转指令,跳到系统...
  • Cadence Allegro 如何设定布线区域和器件布局区域 Route keepout和 Route keepin区别: Route keepout是范围允许布线; Route keepin是范围不允许布线; Package keepin和Package keepout区别: ...
  • offer(1-10题)详解

    千次阅读 2020-01-19 21:37:34
    然后单个查找在这个范围内即使不优化也不会超时。有兴趣的可以自己写一写二分!复杂度O(logn) 代码: public class Solution { public boolean Find ( int target , int [ ] [ ] array ) ...
  • 区域填充算法

    万次阅读 2006-02-24 17:58:00
    区域填充即给出一个区域的边界,要求对边界范围内的所有象素单元赋予指定的颜色代码。区域填充中最常用的是多边形填色,本节中我们就以此为例讨论区域填充算法。多边形填色即给出一个多边形的边界,要求对多边形边界...
  • * 判断是否在范围内 * @param raduis 圆的半径 * @param lat 点的纬度 * @param lng 点的经度 * @param lat1 圆的纬度 * @param lng1 圆的经度 * @return */ public boolean isInRange(int raduis,B...
  • 空间分析之区域分析

    万次阅读 热门讨论 2012-08-24 17:12:53
    空间分析扩展中,有关区域分析,提供了如下工具: 可以将其分为这样几类: 一、确定区域中类的面积的工具 面积制表(Tabulate Area) ...1)....2)....3). 每个记录将存储每个区域内每个类的面积。
  • 判断touch事件点是否在view范围内

    千次阅读 2012-03-14 15:53:36
    private Rect mChangeImageBackgroundRect = null;  private boolean isInChangeImageZone(View view, int x, int y) {  if (null == mChangeImageBackgroundRect) { ... mChangeImageBack
  • 计算机图形学——区域填充算法

    千次阅读 2019-10-07 15:08:04
    区域填充:将区域内的一点(常称【种子点】)赋予给定颜色,然后将这种颜色扩展到整个区域内的过程。 区域填充算法要求区域是连通的,因为只有在连通区域中,才可能将种子点的颜色扩展到区域内的其它点。 1、区域有...
  • 接上文 计算机图形学 学习笔记(二):多边形扫描转换:X扫描线算法 和 改进的X扫描线算法光栅图形学算法2.6 多边形的区域填充算法区域:已经表示成点阵样式的填充图形,是像素的集合区域填充:区域内的一点...
  • 感兴趣区域(Volum of Interest,VOI)是图像内部的一个子区域。在VTK中vtkExtractVOI类实现由用户指定的区域范围提取图像的子图像。该Filter的输入和输出都是一个vtkImageData,因此其结果可以直接作为图像保存。...
  • Android 扩大view点击范围

    千次阅读 2015-03-19 11:15:37
    7~10毫米,这是一个用户手指能准确并且舒适触摸的区域。 如下图所示,你的UI元素可能小于48dp,图标仅有32dp,按钮仅有40dp,但是他们的实际可操作焦点区域最好都应达到48dp的大小。 为使小的UI区域获得良好的...
  • [计算机图形学经典算法] 区域填充

    千次阅读 2018-01-27 11:03:34
    区域填充是区域内的某一个象素点(种子点)开始,由内向外将填充色扩展到整个区域内的过程。 区域是已经表示成点阵形式的填充图形,它是相互连通的一组像素的集合。(前面描述的 X - 扫描线算法适用于顶点表达...
  • 选定刺激范围以后,再在这个范围内选出 4—9 个间距相等的刺激。正式实验时,每种刺激强度呈现的次数不能少于 20 个,且呈现的次数要相等,呈现的顺序要随机排列。用恒定刺激法测绝对阈限时,绝对阈限的值可以根据...
  • Matlab——离散点的随机区域分配

    千次阅读 2018-04-06 11:11:28
    Matlab——离散点的随机区域分配 假设待定区域现在有200个离散点,我们随机挑选出10个离散点,并以这10个点为中心画半径为R(任意取)的圆。我们知道这10个圆在没有任何交集的情况下,共有1...
  • ROI区域图像操作

    千次阅读 2016-05-20 10:17:12
     如上图所示,就是ROI的一个例子,如果你对图像设置了ROI,那么,Opencv的大多数函数只在该ROI区域内运算(只处理该ROI区域),如果没设ROI的话,就会出来整幅图像。 ROI非常有用,例如我们想把图像中的人脸扣出来...
  • unity中玩家扇形攻击范围

    万次阅读 2017-03-30 14:08:58
    unity中玩家扇形攻击范围在unity rpg游戏中,经常会有主角或者Boss什么的会发动技能攻击,除了有攻击的距离以外,肯定会有攻击的扇形范围。本篇博客就给大家简单的讲解一下范围。 这个是出来60度角的视线范围,在...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 175,345
精华内容 70,138
关键字:

区域内一般指什么范围