各种多边形算法_多边形 变形算法-程序员宅基地

技术标签: canvas  martix  ploygon  

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <script src="/scripts/mathematicsAndPhysics/linearAlgebra/matrix/gl-matrix/2.7.1/dist/gl-matrix.js"></script>
<script src="../../../../scripts/mathematicsAndPhysics/geometry/shape-points/2.0.1/shapPoints.js"></script>
<script src="../../../../scripts/mathematicsAndPhysics/bezierCurve/jsbezier/0.9.3/jsbezier.js"></script>
<script src="../../../../scripts/mathematicsAndPhysics/bezierCurve/bezierjs/2.2.15/bezierjs.js"></script>
    <title></title>
    <style>
        #canvas {
            border: 1px solid #000;
        }
    </style>
</head>
<body>
    <canvas id="canvas">

    </canvas>
        
    <script>
        var canvas = document.getElementById('canvas')
        canvas.width = 1000;
        canvas.height = 1000;
        var ctx = canvas.getContext('2d');
       
       

        // 创建一个
        var rotate = 20 / 180 * Math.PI;
        var rectSize=vec2.fromValues(100,100)
        var rectPosition = vec2.fromValues(100, 100);
        var rectRotatePosition = vec2.rotate(vec2.create(), rectPosition, [0, 0], rotate)

        // 创建一个矩阵
        var m = mat2d.create();
        m = mat2d.translate(mat2d.create(), m, [100, 100]);// 位移
        m = mat2d.scale(mat2d.create(), m, [1, 1]);// 缩放
        m = mat2d.rotate(mat2d.create(), m, rotate);// 旋转20

        var m2=mat2d.multiply(mat2d.create(),mat2d.create(),[2,0,0,2,100,100])
        // 创建一个矩形
        ctx.fillStyle = 'red';
        ctx.setTransform.apply(ctx, m)
        ctx.fillRect(rectPosition[0], rectPosition[1], rectSize[0], rectSize[1]);

   //    ctx.setTransform.apply(ctx, mat2d.create())
        // 创建一个圆
        ctx.beginPath();

        ctx.arc(400, 100, 50, 0, Math.PI * 2);
        ctx.fill();

        function drawPoints(points,fill) {
            ctx.moveTo(points[0], points[1])
            for (var i = 2; i < points.length; i += 2) {
                ctx.lineTo(points[i], points[i + 1])
            }
            if (fill) {
                ctx.fill();
                return;
            }
            ctx.stroke()
        }

        //创建一个三次贝塞尔图形
        var heartPoints = [];
        function heart() {
            var ops = {
                x: 100,
                y: 50,
                width: 30,
                height: 30
            }, x = ops.x, y = ops.y, w = ops.width, h = ops.height;
            ctx.beginPath();
            ctx.moveTo(x, y);

            heartPoints.push([{
                x: x,
                y:y
            }, {
                x: x + w / 2,
                y: y - h * 2 / 3
            }, {
                x: x + w * 2,
                y: y + h / 3

            }, {
                x: x,
                y:y+h
            }])
            heartPoints.push([{
                x: x,
                y: y+h
            }, {
                x: x - w * 2,
                y: y + h / 3
            }, {
                x: x - w / 2,
                y: y - h * 2 / 3

            }, {
                x: x,
                y: y
            }])
            ctx.bezierCurveTo(
              x + w / 2, y - h * 2 / 3,
              x + w * 2, y + h / 3,
              x, y + h
          );
            ctx.bezierCurveTo(
                x - w * 2, y + h / 3,
                x - w / 2, y - h * 2 / 3,
                x, y
            );

            window.isCurve = function (x2, y2) {
                ctx.beginPath();
                ctx.moveTo(x, y);
                        ctx.bezierCurveTo(
                   x + w / 2, y - h * 2 / 3,
                   x + w * 2, y + h / 3,
                   x, y + h
               );
                ctx.bezierCurveTo(
                    x - w * 2, y + h / 3,
                    x - w / 2, y - h * 2 / 3,
                    x, y
                );
           
                if (ctx.isPointInPath(x2, y2)) {
                    return true;
                }
                return false;
            }

            ctx.fill();



            // 曲线转成直线
            var p1=heartPoints[0].reduce(function(a,b){
                return a.concat(b.x,b.y);
            }, [])
            var p2 = heartPoints[1].reduce(function (a, b) {
                return a.concat(b.x, b.y);
            }, [])
            var p1Points = shapPoints.bezierCurveTo.apply(null, p1)
            var p2Points = shapPoints.bezierCurveTo.apply(null, p2)
            console.log(p1Points)
            //drawPoints(p1Points, true)
            // drawPoints(p2Points, true)
            var heartBezierPoints = [];
            var heartLinePoints = [];
            var p4 = p1Points.concat(p2Points);
            for (var i = 0,length=p4.length; i < length; i+=2) {
                heartLinePoints.push([p4[i], p4[i + 1]])

               
            }
            window.heartLinePoints = heartLinePoints;


            var b = new bezierjs(heartPoints[0])
            var b2 = new bezierjs(heartPoints[1])
            var b3 = new bezierjs.PolyBezier([b, b2]);
        
        }
        heart();




        
        function Polygon(points) {

            ctx.moveTo(points[0][0], points[0][1]);
            for (var i = 1, l = points.length; i < l; i++) {
                ctx.lineTo(points[i][0], points[i][1]);
            }
            
        }
        var p2=vec2.fromValues(600,100)
        ctx.beginPath();
        ctx.strokeStyle = 'red';
        ctx.lineWidth = 2;
        var points=[[600,100],[700,100],[750,150],[700,200],[600,200],[550,150]];
        Polygon(points);
        ctx.closePath();
        ctx.stroke();

    
        function contian(a, b) {
            var x = 0;
            return a[0] - b[0] <= x && a[1] - b[1] <= x;
        }
        function windingLine(x0, y0, x1, y1, x, y) {
            if ((y > y0 && y > y1) || (y < y0 && y < y1)) {
                return 0;
            }
            // Ignore horizontal line
            if (y1 === y0) {
                return 0;
            }
            var dir = y1 < y0 ? 1 : -1;
            var t = (y - y0) / (y1 - y0);
            //当交点为两条多边形线的连接点时避免缠绕误差
            // Avoid winding error when intersection point is the connect point of two line of polygon
            if (t === 1 || t === 0) {
                dir = y1 < y0 ? 0.5 : -0.5;
            }

            var x_ = t * (x1 - x0) + x0;

            // If (x, y) on the line, considered as "contain".
            return x_ === x ? Infinity : x_ > x ? dir : 0;
        }

        
        function isAroundEqual(a, b) {
            return Math.abs(a - b) < EPSILON;
        }
        var EPSILON = 1e-8;

        function isAroundEqual(a, b) {
            return Math.abs(a - b) < EPSILON;
        }

         function contain(points, x, y) {
            var w = 0;x
            var p = points[0];

            if (!p) {
                return false;
            }

            for (var i = 1; i < points.length; i++) {
                var p2 = points[i];
                w += windingLine(p[0], p[1], p2[0], p2[1], x, y);
                p = p2;
            }
            var p0 = points[0];
             // 第一个点与最后一个点,值相差differ 大于0.00000001,再
            if (!isAroundEqual(p[0], p0[0]) || !isAroundEqual(p[1], p0[1])) {
                w += windingLine(p[0], p[1], p0[0], p0[1], x, y);
            }

            return w !== 0;
         }



        // 
         function linearRingContainsXY(flatCoordinates, offset, end, stride, x, y) {
             // http://geomalgorithms.com/a03-_inclusion.html
             /**
             版权所有(C / / 2000年softsurfer丹,2012年《星期日泰晤士报
                的这段代码可能会用到的自由……和改性的任何用途
                提供版权通知,这是与包含它。
                softsurfer让好的保单在这个方法的代码,和不能被举行
                liable任何房或imagined损伤的功能从它的使用。
                用户的这段代码必须验证的正确性的方法及其应用。
             */
             let wn = 0;
             let x1 = flatCoordinates[end - stride];
             let y1 = flatCoordinates[end - stride + 1];
             for (; offset < end; offset += stride) {
                 const x2 = flatCoordinates[offset];
                 const y2 = flatCoordinates[offset + 1];
                 if (y1 <= y) {
                     if (y2 > y && ((x2 - x1) * (y - y1)) - ((x - x1) * (y2 - y1)) > 0) {
                         wn++;
                     }
                 } else if (y2 <= y && ((x2 - x1) * (y - y1)) - ((x - x1) * (y2 - y1)) < 0) {
                     wn--;
                 }
                 x1 = x2;
                 y1 = y2;
             }
             return wn !== 0;
         }
         function linearRingsContainsXY(flatCoordinates, offset, ends, stride, x, y) {
             if (ends.length === 0) {
                 return false;
             }
             if (!linearRingContainsXY(flatCoordinates, offset, ends[0], stride, x, y)) {
                 return false;
             }
             for (let i = 1, ii = ends.length; i < ii; ++i) {
                 if (linearRingContainsXY(flatCoordinates, ends[i - 1], ends[i], stride, x, y)) {
                     return false;
                 }
             }
             return true;
         }

        // 绕线算法
         function isContainPoint(points,x,y) {
             var r=0;
             for (var i = 0, length=points.length; i < length; i++) {
                 var j = (i + 1) % length;
                 var x2 = points[i][0], y2 = points[i][1];
                 var x3 = points[j][0], y3 = points[j][1];

                 
                 //  

                 // 判断点是否在两点之间
                 if (y >= y2 && y <= y3 && x < ((x3 - x2) * (y - y2) / (y3 - y2) + x2)) {
                     r++;
                 } else if (y <= y2 && y >= y3 && x < ((x3 - x2) * (y - y2) / (y3 - y2) + x2)) {
                     r--;
                 } 

             }
            return r!=0;
         }
       

         function pointInPolygon(vertices, x, y) {
             var a, b, i, j;
             var xpi, ypi, xpj, ypj;
             var c = false;
             for (i = 0; i < vertices.length; i++) {
                 j = (i + 1) % vertices.length;
                 a = vertices[i];
                 b = vertices[j];
                 xpi = a[0];
                 ypi = a[1];
                 xpj = b[0];
                 ypj = b[1];
                 if ((((ypi <= y) && (y < ypj)) || ((ypj <= y) && (y < ypi))) &&
                     (x < (xpj - xpi) * (y - ypi) / (ypj - ypi) + xpi)) {
                     c = !c;
                 }
             }
             return c;
         }
        // x 100  y 100   150 150  x 200 y 200

         //+ Jonas Raoni Soares Silva
         //@ http://jsfromhell.com/math/is-point-in-poly [rev. #0]

         function isPointInPoly(poly, x,y) {
             var c = false;
             for (var i = -1, l = poly.length, j = l - 1; ++i < l; j = i) {
                 var px = poly[i][0];
                 var py = poly[i][1];
                 var px2 = poly[j][0];
                 var py2 = poly[j][1];

                 if (((py <= y && y < py2) || (py2 <= y &&y < py))&& (x< (px2- px) * (y - py) / (py2 - py) + px)){
                     c = !c;
                 }
             }
             return c;

         }
         function isPointInPath(x, y, poly){
             var num = poly.length;
             var i = 0;
             var j = num - 1;
             var c = false;
             for(;i<num;i++){
                 if (((poly[i][1] > y) != (poly[j][1] > y)) &&
                 (x < poly[i][0] + (poly[j][0] - poly[i][0]) * (y - poly[i][1]) /
                                   (poly[j][1] - poly[i][1]))) {
                     c = true;
                 }
                 j = i
             }
             return c

         }

        document.addEventListener('click', function (e) {

            var x = e.pageX - canvas.offsetLeft, y = e.pageY - canvas.offsetTop;

            var invertM = mat2d.invert(mat2d.create(), m);// 逆阵
         
            var xy2 = vec2.transformMat2d(vec2.create(), vec2.fromValues(x, y), m)
            // 计算当前图形位置
            var xy4 = vec2.transformMat2d(vec2.create(), rectPosition, m)
            // 当前鼠标位置
            var xy3 = vec2.transformMat2d(vec2.create(), vec2.fromValues(x, y), invertM)
            
            // 正方形
            if (contian(rectPosition, xy3) && contian(xy3, vec2.add(vec2.create(), rectPosition, rectPosition)))
            {
                console.log('rect命中');
            }
            // 贝塞尔曲线
            //    console.log('bezier', jsBezier._distanceFromCurve({ x: xy3[0], y: xy3[1] }, heartPoints[0]))
            if (isCurve(x, y)) {
                console.log('heartLine命2中');
            }
            if (pointInPolygon(heartLinePoints, xy3[0], xy3[1])) {
                console.log('heartLine命中');
            }
            // 圆形
            if (vec2.distance([400, 100], xy3) <= 50) {
                console.log('circle命中');
            }
            // 多边形
            if (contain(points, xy3[0], xy3[1])) {
                console.log('polygon命中');
            }
            if (pointInPolygon(points, xy3[0], xy3[1])) {
                console.log('polygon3命中');
            }
            if (isPointInPoly(points, xy3[0], xy3[1])) {
                console.log('polygon4命中');
            }
            if (isContainPoint(points, xy3[0], xy3[1])) {
                console.log('polygon5命中');
            }
            var p2 = points.reduce(function (a, b) { return a.concat(b); }, []);
            if (linearRingsContainsXY(p2,0, [p2.length], 2, xy3[0], xy3[1])) {
                console.log('polygon2命中');
            }
           // console.log(x, y, invertM);

        })

    </script>

</body>
</html>

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/long5305350/article/details/95511744

智能推荐

uniapp实战——实现详情其他部分的结构_uniapp 实现关系图谱-程序员宅基地

文章浏览阅读241次。QQ 1274510382Wechat JNZ_aming商业联盟 QQ群538250800技术搞事 QQ群599020441解决方案 QQ群152889761加入我们 QQ群649347320共享学习 QQ群674240731纪年科技aming网络安全 ,深度学习,嵌入式,机器强化,生物智能,生命科学。叮叮叮:产品已上线 —>关注 官方认证-微信公众号——济南纪年信息科技有限公司民生项目:商城加盟/娱乐交友/创业商圈/外包兼职开发-项目发布/安全项目:态.._uniapp 实现关系图谱

如何查看其他人的ABAP authorization check log_查看authorization-程序员宅基地

文章浏览阅读375次。Created by Jerry Wang on Jul 29, 2014 Go to start of metadata在做middleware相关的scenario操作时,有时候需要evaluate其他user的authorization check log,例如在CRM tcode SMW01里发现BDoc state为validation error,点击show error butto..._查看authorization

12-SIM数据交互之-IMSI=MCC+MNC+MSIN_imsi mcc-程序员宅基地

文章浏览阅读9.9w次。IMSI国际移动用户识别码(International Mobile Subscriber Identification Number)是区别移动用户的标志,储存在SIM卡中,可用于区别移动用户的有效信息。IMSI是15位的十进制数,其结构为:MCC+MNC+MSIN1.MCCMCC(Mobile Country Code,移动国家码)MCC的资源由国际电联(ITU)统一分配和管理,唯一..._imsi mcc

给标签A绑定事件,标签B带参传值触发标签A的事件-程序员宅基地

文章浏览阅读515次。一、id="transfer1"的标签绑定事件$('#transfer1').bind('aEvent',function(event,v1){ v1=v1.substring(1,v1.length-1); var v2=eval("(" + v1 + ")"); layui.use(['transfer', 'layer', 'util'], function(){ var...

你的简历合适且有意义吗?-程序员宅基地

文章浏览阅读69次。 近几个月来,不断有网友请我为他们看一下他们的求职简历,因为他们说他们找工作好久了,可一直没有找到,甚至连个通知面试的电话都没有,于是开始怀疑是简历的问题。 尽管不是专门从事人事方面的,但笔者在这方面还是稍有研究,毕竟以前也有过类似的经历,而且还有过比较多的成功面试经验。为此下面谈一下自己的看法。关于面试简历的书写注意事项在我的《网管员面试宝典》一书中已有较详细介绍,在此仅对几个关键注意..._您看我的简历合适吗

SteamVR Unity工具包_steamvr 稳定unity包-程序员宅基地

文章浏览阅读2.2k次。原文: [AR/VR教程] SteamVR Unity工具包(三):控制器交互 可交互对象(VRTK_InteractableObject)可交互对象脚本被添加到需要用(如控制器)来交互的任何游戏对象上。可用脚本参数如下Touch Interactions 触摸交互· Highlight On Touch:如果勾选,这个对象在控制器触摸它时就_steamvr 稳定unity包

随便推点

simulink建模之电机模型_simulink电机模型-程序员宅基地

文章浏览阅读3w次,点赞36次,收藏273次。simulink建模之电机模型文章目录simulink建模之电机模型0.前言1.原理分析2.具体步骤2.1第一步:最大扭矩和功率模块2.1.1在恒功率区通过转速查表得出力矩值2.2第二步:电机效率模块2.3第三步:求电流3.总结0.前言由于纯电动车开发越来越火,而对于电机的控制就相当于传统燃油车的发动机的控制,并且电机在生活中使用特别广泛,因此电机仿真模型在整车仿真中具有重要的意义。1.原..._simulink电机模型

Python 类型转换_python y=str(x)-程序员宅基地

文章浏览阅读218次。python 类型转换很简单 想转什么类型只需要在,要转的类型(转的类型) 即可具体的如下x = 10x = type(x)# 确认当前x的类型 打印结果:<type 'int'>print (x)# int 转 String 类型y = str(x)y =type(y)# 确认当前y的类型 打印结果:<type 'str'>print (y)# String 转 int 类型x = "10"y =int(x)y =type(y)# 确认当前y_python y=str(x)

AndroidStudio各种疑难杂症_one or more plugins require a higher android sdk v-程序员宅基地

文章浏览阅读315次。错误1:Failed to find Build Tools revision 25.0.3方法:File->settings->Android SDK->SDK Tools点击右下角show Package Details 勾选你需要的版本下载即可,如我这里就是25.0.3..._one or more plugins require a higher android sdk version.

UE4学习笔记——粒子发射器_ue4怎样让粒子一开始就发射-程序员宅基地

文章浏览阅读4.7k次,点赞3次,收藏6次。#生成并设置好粒子系统#在面板空白处右击打开菜单,并在向量场中选中整体向量场#在整体向量场的细节面板中找到整体向量场的缩放,此处需设置为1#在必需的细节面板中找到使用局部空间,确保此处处于为启用状态#点击下图中红框内的边界旁的三角号,找到并选中设置固定边界,然后保存#作用的效果如下等待后续更新。。。[1]:https://docs.unrealengine.com/zh-CN/Engine/Rendering/ParticleSystems/VectorFields/index.h_ue4怎样让粒子一开始就发射

iOS 实现步骤进度条-程序员宅基地

文章浏览阅读1.6k次。Linux编程点击右侧关注,免费入门到精通!作者丨独木舟的木https://www.jianshu.com/p/fb471ca68a1b步骤进度条效果参考iOS UIKi..._ios 步骤进度条

Promise详解(resolve,reject,catch)_promise((resolve, reject)-程序员宅基地

文章浏览阅读4.6w次,点赞41次,收藏117次。一:何为Promise?为了直观一点,首先我们采用console.dir(Promise)看一下它的结构组成。从上面的图片中我们可以到,Promise其实是一个构造函数,它有resolve,reject,race等静态方法;它的原型(prototype)上有then,catch方法,因此只要作为Promise的实例,都可以共享并调用Promise.prototype上面的方法(t..._promise((resolve, reject)