精华内容
下载资源
问答
  • flash MX中怎么画多边形 一用Transform 面板 我们以正五边形为例 1新建一文件在场景任画一条直线按 F8转换为影片把中心定为左上角 如图1所示 图1中心定在左上角 2选中直线按ctrl+T调出Transform 面板并在Rotate框...
  • 或者帮我把下面这个多边形改下也行 CClientDC dcClient(m_hWnd); Graphics g(dcClient.m_hDC); g.SetSmoothingMode(SmoothingModeAntiAlias); Color defaultclr(220,220,220); SolidBrush ...
  • 水平的一对切线,再旋转十度一对相互平行的切线,每隔十度一对切线,一圈要36对,怎么实现?[img=https://img-bbs.csdn.net/upload/201409/29/1412006112_675410.png][/img]
  • 画多边形主要分为两步: 1,光线和多边形所在的平面相交,求得交点; 2,判断交点是否在多边形内;   32.1 光线和多边形所在的平面相交 分别定义光线、多边形多边形所在平面。光线和平面的方程如下:(注意...

    画多边形主要分为两步:

    1,光线和多边形所在的平面相交,求得交点;

    2,判断交点是否在多边形内;

     

    32.1 光线和多边形所在的平面相交

    分别定义光线、多边形和多边形所在平面。光线和平面的方程如下:(注意:用到法向量的地方一般都将其标准化。尽管有时候没有必要,但是在某些公式或算法中只能使用标准法向量(而不是法向量)。所以,为了避免特别记忆,统一都进行标准化。)

     

    光线方程:

    多边形:


    平面方程:


    如上Pn=[A, B, C]为平面的单位法向量。D是原点[0, 0, 0]到平面的距离。

    可以先通过多边形任意两条不平行的边对应的向量的叉乘求得平面的法向量;然后代入任意顶点的坐标可以求出常数D。

     

    将(C1)展开,然后代入(C2),如下可以求得t.


     

    用向量表示是这样的:



    通常,我们要求的平面法向量是面向光线的那一条(而不是远离光线的那一条),所以,我们将法向量的方向作如下调整:


    32.2 判断交点是否在多边形内

    在“32.1”中求得:

    多边形的法向量Pn:


    判断交点是否在多边形内的步骤如下:

     

    第一步:将所有点(顶点和交点)投影到二维UV平面。

    (投影是不会改变图的拓扑结构的)

     

    根据法向量Pn=[A, B, C]的各个坐标值的绝对值的大小,选出绝对值最大的作为主坐标。比如:Pn=[-5, 3, 1]则X坐标-5的绝对值最大,则X为主坐标;

    Pn=[-5, 8, 1]则Y坐标8的绝对值最大,则Y为主坐标;

    Pn=[-5, 3, 10]则Z坐标10的绝对值最大,则Z为主坐标;

     

    扔掉所有点的三维坐标中的主坐标,剩余的两个坐标即为二维坐标中的U和V。比如:

    若,Pn=[-5, 3, 1]则X坐标-5的绝对值最大,则X为主坐标

    所有点的X坐标都扔掉,剩余Y、Z坐标:

    交点:Ri=[Xi, Yi, Zi]--------------------------[Yi, Zi]即为[Ui, Vi]

    顶点:Gn=[Xn, Yn, Zn]----------------------[Yn, Zn]即为[Un, Vn]

     

    第二步:将UV平面上交点[Ui, Vi]平移到UV的原点[0, 0]。

    则:

    交点:Ri=[Xi, Yi, Zi]--------------------------[Yi, Zi]即为[Ui,Vi]-------------------[0, 0]

    顶点:Gn=[Xn, Yn, Zn]----------------------[Yn, Zn]即为[Un,Vn]----------------[Un-Ui, Vn-Vi]

     

    第三步:计算从原点出发、沿+U轴的射线与多边形交点的个数。

     

    交点个数为奇数,则Ri在原多边形内;

    交点个数为偶数,则Ri在原多边形外。


    先说明一点,像F点这样的顶点在坐标轴上,我们认为是在坐标轴上方的(即EF和坐标轴相交,FA不和坐标轴相交)

    具体怎么数多边形和+U轴的交点个数呢?

    假设多边形的顶点顺序为ABCDEF(即六条边为:AB、BC、CD、DE、EF、FA。注意:第一个顶点A会被使用两次)。一条边一条边依次判断是否和+U轴相交,每条边的判断依据如下:

     

    1,边要与+U轴相交,前提是必须与U轴(含-U和+U)相交:也就是前后两个顶点的V坐标必须是异号的

    2,前后两顶点异号的边与U轴相交有如下8种情况:



    32.3 看C++代码实现

    ----------------------------------------------polygon.h------------------------------------------

    polygon.h

    #ifndef POLYGON_H
    #define POLYGON_H
    
    #include <hitable.h>
    
    
    class polygon : public hitable
    {
        public:
            polygon() {}
            polygon(vec3 *v, int n, material *m) : vertexes(v), number(n), ma(m) {}
            virtual bool hit(const ray& r, float tmin, float tmax, hit_record& rec) const;
            vec3 *vertexes;/*多边形顶点数组/列表首地址*/
            int number;/*多边形顶点的个数*/
            material *ma;/*多边形的材质*/
    };
    
    #endif // POLYGON_H
    


    ----------------------------------------------polygon.cpp------------------------------------------

    polygon.cpp

    #include "polygon.h"
    #include "vec2.h"
    #include "log.h"
    
    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    bool in_polygon_test(vec2 *vertexes_uv, int number) {
    /*根据多边形在UV平面的投影与+U轴交点的个数来判断交点是否在多边形内*/
            int sh, nsh;
            int nc = 0;
            if(vertexes_uv[0].v() < 0) { sh = -1;}
            else { sh = 1;}
            for(int j=0; j<number; j++) {
                if(vertexes_uv[j+1].v() < 0) { nsh = -1;}
                else { nsh = 1;}
                if(sh != nsh) {//前后两个顶点的纵坐标V异号
                    if((vertexes_uv[j].u() > 0) && (vertexes_uv[j+1].u() >0)) { nc++;}
    /*前后两个顶点的横坐标U都大于零,这条边必定过+U轴*/
                    else
                        if((vertexes_uv[j].u() > 0) || (vertexes_uv[j+1].u() >0)) {
    /*前后两个顶点的横坐标异号,这条边过+U轴的条件是:Uj - Vj /k > 0*/
                            if(vertexes_uv[j].u() - (vertexes_uv[j].v())*(vertexes_uv[j+1].u()-vertexes_uv[j].u())/(vertexes_uv[j+1].v()-vertexes_uv[j].v()) > 0) { nc++;}
                        }
                }
                sh = nsh;
            }
            if((nc)%(2)) {return true;}//交点数为奇数,原交点在多边形内,返回true
            else {return false;}
    }
    
    bool polygon::hit(const ray& r, float t_min, float t_max, hit_record& rec) const {
            vec3 poly_n;
            for(int i=0; i<number-2; i++) {
    /*以连续三个顶点构成的两个平行的向量的叉乘得到平面的法向量,并对法向量进行标准化*/
                poly_n = unit_vector(cross((vertexes[i]-vertexes[i+1]), (vertexes[i+1]-vertexes[i+2])));
    //determine the normal of the plane
                if(!vector_equ(poly_n, vec3(0,0,0))) {//法向量不为0,即所选的两个向量不平行
                    break;
                }
            }
            float poly_d = -(dot(poly_n, vertexes[0]));
    /*determine the distance from the origin to the plane。随便找一个顶点(这里找的是第一个顶点),代入方程求得参数D(即为原点到平面的距离)*/
            float vd = dot(poly_n, r.direction());
            float v0 = -(dot(poly_n, r.origin()) + poly_d);
    
            if(vd == 0) {//the ray is parallel to the polygon plane
                return false;
            }
            else {
                float t = v0/vd;//determine t and intersection pi
                vec3 pi = r.point_at_parameter(t);//get the coordinates of pi
    
                float temp = abs(poly_n.x());
                int i = 1;
                if(temp <= abs(poly_n.y())) {
                    temp = abs(poly_n.y());
                    i++;
                }
                if(temp <= abs(poly_n.z())) {
                    i++;
                }
                /*find the dominant coordinate, X, Y, or Z?
                i=1: means that X is the dominant coordinate;
                i=2: means that Y is the dominant coordinate;
                i=3: means that Z is the dominant coordinate;
                */
    
    /*the following “switch…case…” throw the dorminant coordinate of 3-d vector, then we get 2-d vector in uv-plane*/
                vec2 vertexes_uv[number+1];
    //声明二维向量数组。(需要创建一个vec2的类,类似与vec3,不赘述)
                switch (i) {
                case 1://throw X coordinates
                    for(int i=0; i<number; i++) {
                        vertexes_uv[i] = vec2(vertexes[i].y(),vertexes[i].z());
                    }
                    vertexes_uv[number] = vec2(pi.y(),pi.z());
                    break;
                case 2: //throw Y coordinates
                    for(int i=0; i<number; i++) {
                        vertexes_uv[i] = vec2(vertexes[i].x(),vertexes[i].z());
                    }
                    vertexes_uv[number] = vec2(pi.x(),pi.z());
                    break;
               case 3: //throw Z coordinates
                    for(int i=0; i<number; i++) {
                        vertexes_uv[i] = vec2(vertexes[i].x(),vertexes[i].y());
                    }
                    vertexes_uv[number] = vec2(pi.x(),pi.y());
                    break;
                }
    
                /*this “for” loop moves intersection uv-coordinate to origin.
                so all the vertexes substract intersection uv-coordinate.*/
                for(int i=0; i<number; i++) {
                    vertexes_uv[i] = vertexes_uv[i] - vertexes_uv[number];
                }
                vertexes_uv[number] = vertexes_uv[0];
    /*the first vertex will be used twice, so set the first vertex to the last position of the array, so that we get the whole vertexes loop*/
                if(in_polygon_test(vertexes_uv,number)) {
    /*check if the intersection locates inside the polygon or not. If the intersection is inside the polygon, the current ray hits the polygon, otherwise, misses the polygon. Hits: store related information about the polygon and return true, note that the poly_n should be the unit vector. Misses: return false.*/
                    if (t < t_max && t > t_min) {
                        rec.t = t;
                        rec.p = r.point_at_parameter(rec.t);
                        rec.normal = poly_n;
                        rec.mat_ptr = ma;
                        return true;
                    }
                     return false;
                }
                return false;
            }
    }
    


    ----------------------------------------------main.cpp------------------------------------------

    main.cpp

    main()函数中

    //triangle1, the light pink metal one
            vec3 vertexes3_1[3];
            vertexes3_1[0] = vec3(3,-0.5,-2);
            vertexes3_1[1] = vec3(-1,-0.5,-4);
            vertexes3_1[2] = vec3(0,5,-3);
    //triangle2, the green lambertian one
            vec3 vertexes3_2[3];
            vertexes3_2[0] = vec3(-1,1.5,-1);
            vertexes3_2[1] = vec3(-3,1.5,-1);
            vertexes3_2[2] = vec3(-2,3.5,-1);
    //pentagon
            vec3 vertexes5[5];
            vertexes5[0] = vec3(3.3000,1.3000,0.0000);
            vertexes5[1] = vec3(2.3489,0.6090,0.0000);
            vertexes5[2] = vec3(2.7122,-0.5090,0.0000);
            vertexes2[3] = vec3(3.8878,-0.5090,0.0000);
            vertexes5[4] = vec3(4.2511,0.6090,0.0000);
    
            hitable *list[5];
            list[0] = new polygon(vertexes3_2, 3, new lambertian(vec3(0.3, 0.8, 0.0)));
            list[1] = new sphere(vec3(0,-100.5,-1), 100, new lambertian(vec3(0.8, 0.8, 0.0)));
            list[2] = new sphere(vec3(-2,0.5,-1), 1, new lambertian(vec3(0.5, 0.7, 0.6)));
            list[3] = new polygon(vertexes3_1, 3, new metal(vec3(0.8, 0.6, 0.5), 0.0));
            list[4] = new polygon(vertexes5, 5, new lambertian(vec3(1.0, 0.0, 0.0)));
            hitable *world = new hitable_list(list,5);
    
            vec3 lookfrom(0,0,10);
            vec3 lookat(0,1,-1);
            float dist_to_focus = (lookfrom - lookat).length();
            float aperture = 0.0;
            camera cam(lookfrom, lookat, vec3(0,1,0), 30, float(nx)/float(ny), aperture, 0.7*dist_to_focus);
    

    两个漫射球,一个大的(半径为100),一个小的(半径为1);

    两个三角形,一个漫射材料,一个镜面材料;

    一个五边形,漫射材料。

     

    输出图片如下:


    意外发现:多边形顶点的定义顺序决定着最终的多边形形状。

    比如:

    当五边形的顶点定义顺序为ABCDE时(即之前的图片),赋值为:

    //pentagon

            vec3 vertexes5[5];

            vertexes5[0] =vec3(3.3000,1.3000,0.0000);

            vertexes5[1] =vec3(2.3489,0.6090,0.0000);

            vertexes5[2] =vec3(2.7122,-0.5090,0.0000);

            vertexes2[3] =vec3(3.8878,-0.5090,0.0000);

            vertexes5[4] =vec3(4.2511,0.6090,0.0000);

    若将五边形的顶点定义顺序改为ACEBD,会是什么图片呢??赋值为:

    //pentacle

            vec3 vertexes5[5];

            vertexes5[0] = vec3(3.3000,1.3000,0.0000);

            vertexes5[1] =vec3(2.7122,-0.5090,0.0000);

            vertexes5[2] =vec3(4.2511,0.6090,0.0000);

            vertexes5[3] =vec3(2.3489,0.6090,0.0000);

            vertexes5[4] =vec3(3.8878,-0.5090,0.0000);

    输出图片是这样的:



    ~咦,五角星怎么是空心的呢?


    根据我们的算法,从原点沿着+U轴的射线与多边形的交点个数为奇数时,表示原交点在多边形内,否则在多边形外。

    如上图,从O沿着+U轴交点(蓝点)是两个,不是奇数,所以说O点在多边形外。上图中心的蓝色五边形都是这种情况,所以,这个蓝色五边形不属于多边形ACEBD。

    这个结果和实际情况有异,我们希望这个蓝色五边形属于多边形ACEBD。

    怎么修改我们的算法呢???


    以多边形ACEBD为例,该多边形有五条边:AC、CE、EB、BD、DA。与+U轴相交的是CE和DA。

    对于CE,是从-V轴到+V轴,所以NC=NC-1;

    对于DA,是从-V轴到+V轴,所以NC=NC-1;

    所以NC的最终结果是-2,不是0,所以O点在多边形ACEBD内。

     

    顺便提一下(与当前问题无关):什么情况下NC=NC+1呢?将上面两条边反过来EC、AD,则是从+V轴到-V轴,所以NC=NC+1。

     

    怎么修改代码呢???

     

    ----------------------------------------------polygon.cpp------------------------------------------

    polygon.cpp

    bool in_polygon_test2(vec2 *vertexes_uv, int number) {
    /*根据winding number是否为0来判断原交点是否在多边形内*/
            int sh, nsh;
            int nc = 0;
            if(vertexes_uv[0].v() < 0) { sh = -1;}
            else { sh = 1;}
            for(int j=0; j<number; j++) {
                if(vertexes_uv[j+1].v() < 0) { nsh = -1;}
                else { nsh = 1;}
                if(sh != nsh) {
    /*前后两个顶点的纵坐标V异号。所以,大的V值为正,小的V值为负。前顶点的比后顶点的大,则是从+V到-V,则NC=NC+1;反之,从-V到+V,NC=NC-1*/
                    if((vertexes_uv[j].u() > 0) && (vertexes_uv[j+1].u() >0)) {
                        if(vertexes_uv[j].v() > vertexes_uv[j+1].v()) { nc = nc + 1;}
                        else { nc = nc - 1;}
                    }
                    else
                        if((vertexes_uv[j].u() > 0) || (vertexes_uv[j+1].u() >0)) {
                            if(vertexes_uv[j].u() - (vertexes_uv[j].v())*(vertexes_uv[j+1].u()-vertexes_uv[j].u())/(vertexes_uv[j+1].v()-vertexes_uv[j].v()) > 0) {
                                if(vertexes_uv[j].v() > vertexes_uv[j+1].v()) { nc = nc + 1;}
                                else { nc = nc - 1;}
                            }
                        }
                }
                sh = nsh;
            }
            if(nc != 0) {return true;}
            else {return false;}
    }
    

    采用新的判定算法后,输出图片为:


    接下来再在图片中添加一个介质三角形(因为漫射材料、镜面材料的多边形多有了,只差介质材料了)

    //triangle1, the light pink metal one
            vec3 vertexes3_1[3];
            vertexes3_1[0] = vec3(3,-0.5,-2);
            vertexes3_1[1] = vec3(-1,-0.5,-4);
            vertexes3_1[2] = vec3(0,5,-3);
    //triangle2, the green lambertian one
            vec3 vertexes3_2[3];
            vertexes3_2[0] = vec3(-1,1.5,-1);
            vertexes3_2[1] = vec3(-3,1.5,-1);
            vertexes3_2[2] = vec3(-2,3.5,-1);
    //triangle3, the bigger dielectric one
            vec3 vertexes3_4[3];
            vertexes3_4[0] = vec3(4,-0.5,4);
            vertexes3_4[1] = vec3(-4,-0.5,4);
            vertexes3_4[2] = vec3(0,4,4);
    //pentacle
            vec3 vertexes5[5];
            vertexes5[0] = vec3(3.3000,1.3000,0.0000);
            vertexes5[1] = vec3(2.7122,-0.5090,0.0000);
            vertexes5[2] = vec3(4.2511,0.6090,0.0000);
            vertexes5[3] = vec3(2.3489,0.6090,0.0000);
            vertexes5[4] = vec3(3.8878,-0.5090,0.0000);
    
            hitable *list[6];
            list[0] = new polygon(vertexes3_2, 3, new lambertian(vec3(0.3, 0.8, 0.0)));
            list[1] = new sphere(vec3(0,-100.5,-1), 100, new lambertian(vec3(0.8, 0.8, 0.0)));
            list[2] = new sphere(vec3(-2,0.5,-1), 1, new lambertian(vec3(0.5, 0.7, 0.6)));
            list[3] = new polygon(vertexes3_1, 3, new metal(vec3(0.8, 0.6, 0.5), 0.0));
            list[4] = new polygon(vertexes5, 5, new lambertian(vec3(1.0, 0.0, 0.0)));
            list[5] = new polygon(vertexes3_4, 3, new dielectric(1.5));
            hitable *world = new hitable_list(list,6);
    
            vec3 lookfrom(0,0,10);
            vec3 lookat(0,1,-1);
            float dist_to_focus = (lookfrom - lookat).length();
            float aperture = 0.0;
            camera cam(lookfrom, lookat, vec3(0,1,0), 30, float(nx)/float(ny), aperture, 0.7*dist_to_focus);
    

    加介质三角形之前:


    折射系数为1.5:

    折射系数为3:

    折射系数为4.5:

    折射系数为9:


    上面加的介质三角形比较大,下面将介质三角形改小一点。

    //triangle3, the smaller dielectric one

            vec3vertexes3_3[3];

           vertexes3_3[0] = vec3(1.5,-0.5,4);

           vertexes3_3[1] = vec3(-1.5,-0.5,4);

           vertexes3_3[2] = vec3(0,2,4);

    加介质三角形之前(还是这张图):


    折射系数为1.5:

    折射系数为3:

    折射系数为4.5:

    折射系数为9:






    展开全文
  • ![图片说明](https://img-ask.csdn.net/upload/201606/28/1467106049_512103.png) !... 如图,第一张图片的数据是通过第二张图片从数据库循环得来的,读取sqlserver数据库中的坐标显示之前多边形???
  • 匿名用户1级2016-04-24 回答一、多边形类:polygon.jsvar Point = function (x, y) {this.x = x;this.y = y;};var Polygon = function (centerX, centerY, radius, sides, startAngle, strokeStyle, fillStyle, ...

    匿名用户

    1级

    2016-04-24 回答

    一、多边形类:polygon.js

    var Point = function (x, y) {

    this.x = x;

    this.y = y;

    };

    var Polygon = function (centerX, centerY, radius, sides, startAngle, strokeStyle, fillStyle, filled) {

    this.x = centerX;//外接圆心x坐标

    this.y = centerY;

    this.radius = radius;//外接圆半径

    this.sides = sides;//边数

    this.startAngle = startAngle;//开始角度

    this.strokeStyle = strokeStyle;

    this.fillStyle = fillStyle;

    this.filled = filled;

    };

    Polygon.prototype = {

    getPoints: function () {//获取多边形所有顶点

    var points = [],

    angle = this.startAngle || 0;

    for (var i=0; i < this.sides; ++i) {

    points.push(new Point(this.x + this.radius * Math.sin(angle),

    this.y - this.radius * Math.cos(angle)));

    angle += 2*Math.PI/this.sides;

    }

    return points;

    },

    createPath: function (context) {//创建多边形路径

    var points = this.getPoints();

    context.beginPath();

    context.moveTo(points[0].x, points[0].y);

    for (var i=1; i < this.sides; ++i) {

    context.lineTo(points[i].x, points[i].y);

    }

    context.closePath();

    },

    stroke: function (context) {//对多边形描边

    context.save();

    this.createPath(context);

    context.strokeStyle = this.strokeStyle;

    context.stroke();

    context.restore();

    },

    fill: function (context) {//填充

    context.save();

    this.createPath(context);

    context.fillStyle = this.fillStyle;

    context.fill();

    context.restore();

    },

    move: function (x, y) {

    this.x = x;

    this.y = y;

    },

    };

    二、HTML文件

    拖动多边形

    body{

    background: #eeeeee;

    }

    #dragDiv {

    position: absolute;

    left: 25px;

    top: 50px;

    }

    #controls {

    position: absolute;

    left: 25px;

    top: 25px;

    }

    #canvas {

    background: #ffffff;

    cursor: crosshair;

    margin-left: 10px;

    margin-top: 10px;

    -webkit-box-shadow: 4px 4px 8px rgba(0,0,0,0.5);

    -moz-box-shadow: 4px 4px 8px rgba(0,0,0,0.5);

    box-shadow: 4px 4px 8px rgba(0,0,0,0.5);

    }

    Canvas not supported

    描边颜色:

    red

    green

    blue

    orange

    goldenrod

    navy

    purple

    填充颜色:

    semi-transparent red

    green

    orange

    goldenrod

    navy

    purple

    边数:

    4

    6

    8

    10

    12

    20

    开始角度:

    0

    22.5

    45

    67.5

    90

    是否填充

    编辑:

    三、JS文件 example.js

    var canvas = document.getElementById('canvas'),

    context = canvas.getContext('2d'),

    //清除按钮

    eraseAllButton = document.getElementById('eraseAllButton'),

    //描边颜色

    strokeStyleSelect = document.getElementById('strokeStyleSelect'),

    //画多边形的开始角度

    startAngleSelect = document.getElementById('startAngleSelect'),

    //填充颜色

    fillStyleSelect = document.getElementById('fillStyleSelect'),

    //不否填充

    fillCheckbox = document.getElementById('fillCheckbox'),

    //进入编辑

    editCheckbox = document.getElementById('editCheckbox'),

    //边数

    sidesSelect = document.getElementById('sidesSelect'),

    //canvas位图数据

    drawingSurfaceImageData,

    //记录鼠标按下的位置

    mousedown = {},

    //橡皮筋矩形框

    rubberbandRect = {},

    dragging = false,//是否在拖动状态

    draggingOffsetX,

    draggingOffsetY,

    sides = 8,

    startAngle = 0,

    guidewires = true,

    editing = false,

    //保存已绘制的多边形

    polygons = [];

    // Functions..........................................................

    //画网络线

    function drawGrid(color, stepx, stepy) {

    context.save()

    context.shadowColor = undefined;

    context.shadowBlur = 0;

    context.shadowOffsetX = 0;

    context.shadowOffsetY = 0;

    context.strokeStyle = color;

    context.fillStyle = '#ffffff';

    context.lineWidth = 0.5;

    context.fillRect(0, 0, context.canvas.width, context.canvas.height);

    context.beginPath();

    for (var i = stepx + 0.5; i < context.canvas.width; i += stepx) {

    context.moveTo(i, 0);

    context.lineTo(i, context.canvas.height);

    }

    context.stroke();

    context.beginPath();

    for (var i = stepy + 0.5; i < context.canvas.height; i += stepy) {

    context.moveTo(0, i);

    context.lineTo(context.canvas.width, i);

    }

    context.stroke();

    context.restore();

    }

    //窗口坐标转canvas坐标

    function windowToCanvas(x, y) {

    var bbox = canvas.getBoundingClientRect();

    return { x: x - bbox.left * (canvas.width / bbox.width),

    y: y - bbox.top * (canvas.height / bbox.height)

    };

    }

    // 保存或恢复已绘制的画面...................................

    function saveDrawingSurface() {

    drawingSurfaceImageData = context.getImageData(0, 0,canvas.width,canvas.height);

    }

    function restoreDrawingSurface() {

    context.putImageData(drawingSurfaceImageData, 0, 0);

    }

    // 画多边形.....................................................

    function drawPolygon(polygon) {

    context.beginPath();

    polygon.createPath(context);

    polygon.stroke(context);

    if (fillCheckbox.checked) {

    polygon.fill(context);

    }

    }

    // 更新橡皮筋矩形框...................................................

    function updateRubberbandRectangle(loc) {

    rubberbandRect.width = Math.abs(loc.x - mousedown.x);

    rubberbandRect.height = Math.abs(loc.y - mousedown.y);

    if (loc.x > mousedown.x) rubberbandRect.left = mousedown.x;

    else rubberbandRect.left = loc.x;

    if (loc.y > mousedown.y) rubberbandRect.top = mousedown.y;

    else rubberbandRect.top = loc.y;

    }

    //以鼠标按下点为圆心,橡皮筋框宽为半径创建多边形

    function drawRubberbandShape(loc, sides, startAngle) {

    var polygon = new Polygon(mousedown.x, mousedown.y,

    rubberbandRect.width,

    parseInt(sidesSelect.value),

    (Math.PI / 180) * parseInt(startAngleSelect.value),

    context.strokeStyle,

    context.fillStyle,

    fillCheckbox.checked);

    drawPolygon(polygon);//画多边形

    if (!dragging) {//保存这个多边形

    polygons.push(polygon);

    }

    }

    //更新橡皮筋

    function updateRubberband(loc, sides, startAngle) {

    updateRubberbandRectangle(loc);

    drawRubberbandShape(loc, sides, startAngle);

    }

    // 网络线.................................................

    function drawHorizontalLine (y) {

    context.beginPath();

    context.moveTo(0,y+0.5);

    context.lineTo(context.canvas.width,y+0.5);

    context.stroke();

    }

    function drawVerticalLine (x) {

    context.beginPath();

    context.moveTo(x+0.5,0);

    context.lineTo(x+0.5,context.canvas.height);

    context.stroke();

    }

    function drawGuidewires(x, y) {

    context.save();

    context.strokeStyle = 'rgba(0,0,230,0.4)';

    context.lineWidth = 0.5;

    drawVerticalLine(x);

    drawHorizontalLine(y);

    context.restore();

    }

    //绘制保存的所有多边形

    function drawPolygons() {

    polygons.forEach( function (polygon) {

    drawPolygon(polygon);

    });

    }

    希望能够帮助到你!

    展开全文
  • 我需要知道如何在画布上绘制多边形。 不使用jQuery或类似的东西。9个解决方案137 votes创建一个moveTo和lineTo(实时演示)的路径:var ctx = canvas.getContext('2d');ctx.fillStyle = '#f00';ctx.beginPath();ctx....

    javascript - 如何在HTML5画布上绘制多边形?

    我需要知道如何在画布上绘制多边形。 不使用jQuery或类似的东西。

    9个解决方案

    137 votes

    创建一个moveTo和lineTo(实时演示)的路径:

    var ctx = canvas.getContext('2d');

    ctx.fillStyle = '#f00';

    ctx.beginPath();

    ctx.moveTo(0, 0);

    ctx.lineTo(100,50);

    ctx.lineTo(50, 100);

    ctx.lineTo(0, 90);

    ctx.closePath();

    ctx.fill();

    phihag answered 2019-06-21T12:21:08Z

    31 votes

    //poly [x,y, x,y, x,y.....];

    var poly=[ 5,5, 100,50, 50,100, 10,90 ];

    var canvas=document.getElementById("canvas")

    var ctx = canvas.getContext('2d');

    ctx.fillStyle = '#f00';

    ctx.beginPath();

    ctx.moveTo(poly[0], poly[1]);

    for( item=2 ; item < poly.length-1 ; item+=2 ){ctx.lineTo( poly[item] , poly[item+1] )}

    ctx.closePath();

    ctx.fill();

    canvastag answered 2019-06-21T12:21:25Z

    25 votes

    来自[http://www.scienceprimer.com/drawing-regular-polygons-javascript-canvas:]

    以下代码将绘制六边形。 更改边数以创建不同的正多边形。

    // hexagon

    var numberOfSides = 6,

    size = 20,

    Xcenter = 25,

    Ycenter = 25;

    cxt.beginPath();

    cxt.moveTo (Xcenter + size * Math.cos(0), Ycenter + size * Math.sin(0));

    for (var i = 1; i <= numberOfSides;i += 1) {

    cxt.lineTo (Xcenter + size * Math.cos(i * 2 * Math.PI / numberOfSides), Ycenter + size * Math.sin(i * 2 * Math.PI / numberOfSides));

    }

    cxt.strokeStyle = "#000000";

    cxt.lineWidth = 1;

    cxt.stroke();

    Andrew Staroscik answered 2019-06-21T12:21:58Z

    8 votes

    //create and fill polygon

    CanvasRenderingContext2D.prototype.fillPolygon = function (pointsArray, fillColor, strokeColor) {

    if (pointsArray.length <= 0) return;

    this.moveTo(pointsArray[0][0], pointsArray[0][1]);

    for (var i = 0; i < pointsArray.length; i++) {

    this.lineTo(pointsArray[i][0], pointsArray[i][1]);

    }

    if (strokeColor != null && strokeColor != undefined)

    this.strokeStyle = strokeColor;

    if (fillColor != null && fillColor != undefined) {

    this.fillStyle = fillColor;

    this.fill();

    }

    }

    //And you can use this method as

    var polygonPoints = [[10,100],[20,75],[50,100],[100,100],[10,100]];

    context.fillPolygon(polygonPoints, '#F00','#000');

    Jignesh Variya answered 2019-06-21T12:22:16Z

    3 votes

    这是一个甚至支持顺时针/逆时针绘图的功能,您可以使用非零缠绕规则控制填充。

    这是一篇关于它如何工作的完整文章。

    // Defines a path for any regular polygon with the specified number of sides and radius,

    // centered on the provide x and y coordinates.

    // optional parameters: startAngle and anticlockwise

    function polygon(ctx, x, y, radius, sides, startAngle, anticlockwise) {

    if (sides < 3) return;

    var a = (Math.PI * 2)/sides;

    a = anticlockwise?-a:a;

    ctx.save();

    ctx.translate(x,y);

    ctx.rotate(startAngle);

    ctx.moveTo(radius,0);

    for (var i = 1; i < sides; i++) {

    ctx.lineTo(radius*Math.cos(a*i),radius*Math.sin(a*i));

    }

    ctx.closePath();

    ctx.restore();

    }

    // Example using the function.

    // Define a path in the shape of a pentagon and then fill and stroke it.

    context.beginPath();

    polygon(context,125,125,100,5,-Math.PI/2);

    context.fillStyle="rgba(227,11,93,0.75)";

    context.fill();

    context.stroke();

    John R answered 2019-06-21T12:22:53Z

    1 votes

    您可以使用与以下相同的lineTo()方法:  var objctx = canvas.getContext(&#39; 2d&#39;);

    objctx.beginPath();

    objctx.moveTo(75, 50);

    objctx.lineTo(175, 50);

    objctx.lineTo(200, 75);

    objctx.lineTo(175, 100);

    objctx.lineTo(75, 100);

    objctx.lineTo(50, 75);

    objctx.closePath();

    objctx.fillStyle = "rgb(200,0,0)";

    objctx.fill();

    如果你不想填充多边形,请在fill()处使用stroke()方法

    您还可以查看以下内容:[http://www.authorcode.com/draw-and-fill-a-polygon-and-triangle-in-html5/]

    谢谢

    ankur answered 2019-06-21T12:23:39Z

    1 votes

    除了@canvastag,使用while循环与shift我认为更简洁:

    var canvas = document.getElementById('canvas');

    var ctx = canvas.getContext('2d');

    var poly = [5, 5, 100, 50, 50, 100, 10, 90];

    // copy array

    var shape = poly.slice(0);

    ctx.fillStyle = '#f00'

    ctx.beginPath();

    ctx.moveTo(shape.shift(), shape.shift());

    while(shape.length) {

    ctx.lineTo(shape.shift(), shape.shift());

    }

    ctx.closePath();

    ctx.fill();

    Koen. answered 2019-06-21T12:24:07Z

    0 votes

    要制作一个简单的六边形而不需要循环,只需使用beginPath()函数即可。 确保你的canvas.getContext(&#39; 2d&#39;)等于ctx,否则它将无效。

    我还想添加一个名为times的变量,如果需要的话我可以使用它来缩放对象。这就是我不需要更改每个数字。

    // Times Variable

    var times = 1;

    // Create a shape

    ctx.beginPath();

    ctx.moveTo(99*times, 0*times);

    ctx.lineTo(99*times, 0*times);

    ctx.lineTo(198*times, 50*times);

    ctx.lineTo(198*times, 148*times);

    ctx.lineTo(99*times, 198*times);

    ctx.lineTo(99*times, 198*times);

    ctx.lineTo(1*times, 148*times);

    ctx.lineTo(1*times,57*times);

    ctx.closePath();

    ctx.clip();

    ctx.stroke();

    Sabba Keynejad answered 2019-06-21T12:24:43Z

    0 votes

    对于寻找正多边形的人:

    function regPolyPath(r,p,ctx){ //Radius, #points, context

    //Azurethi was here!

    ctx.moveTo(r,0);

    for(i=0; i

    ctx.rotate(2*Math.PI/p);

    ctx.lineTo(r,0);

    }

    ctx.rotate(-2*Math.PI/p);

    }

    使用:

    //Get canvas Context

    var c = document.getElementById("myCanvas");

    var ctx = c.getContext("2d");

    ctx.translate(60,60); //Moves the origin to what is currently 60,60

    //ctx.rotate(Rotation); //Use this if you want the whole polygon rotated

    regPolyPath(40,6,ctx); //Hexagon with radius 40

    //ctx.rotate(-Rotation); //remember to 'un-rotate' (or save and restore)

    ctx.stroke();

    Azurethi answered 2019-06-21T12:25:11Z

    展开全文
  • // GL_POLYGON制定绘制的是多边形 //指定要绘制的物体(此处为包含4个顶点的多边形 glVertex3f(30.25- m_wWidth/2,-30.25 + m_wHeight/2,0.0);//指定顶点,X=0.25 Y=0.25 Z=0.0 glVertex3f(50.75- m_wWidth/...
  • 后来发现还是用回老办法-》链表 比较保险,但是问题来了,怎么把鼠标每一次的点击 传到链表的数组中,下面是直线的. if(m_nDrawType==1) { m_pShape=new CLine;//动态创建 CLine对象 pDoc->m_list...
  • 上面是我在canvas上绘制了多个不规则多边形,如果不是很了解怎么绘制,可以看我上个博客canvas画图 盒子结构 <div class="imgBox" ref="canvas"> <canvas id="myCanvas" width="660px" height="260px" @...

    首先来看看canvas效果图

    canvas画布效果图
    上面是我在canvas上绘制了多个不规则多边形,如果不是很了解怎么绘制,可以看我上个博客canvas画图

    盒子结构

    <div class="imgBox" ref="canvas">
         <canvas id="myCanvas" width="660px" height="260px" @click="getWorkShop"></canvas>
    </div>
    

    样式

    .imgBox {
         width: 100%;
         height: 100%;
         // width: 660px;
         // height: 260px;
         background-color: #c1c8df;
         cursor: pointer;
         #myCanvas {
           width: 100%;
           height: 100%;
         }
       }
    

    这个页面是适配的,imgBox盒子的大小比canvas画布大,canvas是适配上的,这个大小适配方法会影响后面点击画布时有影响,需要在写方法时,判断转化一下

    原理 - 光线投射法

    原理:

    1、从点P出发,任意引一条射线(模拟光线)。

    2、该条射线与多边形A的边相交时,若射线从边的左侧贯穿记录leftCount加1,若射线从边的右侧贯穿记录rightCount加1。

    3、若leftCount-rightCount等于0表示在图形外部,若不等于0表示图形内部。

    点击画布方法
    getWorkShop($el, e) {
    // 画布上是有一张背景图的,且是响应式的,页面的展示的画布与实际样式的画布尺寸不一致,需要转换一下,例如页面时1300 * 500,但是我的画布实际是660 * 260,然后需要比例转换一下
          let cImgW = this.$refs.canvas.clientWidth; // 画布的渲染的宽度
          let cImgH = this.$refs.canvas.clientHeight; // 画布的渲染高度
          let offsetX = $el.offsetX; // 鼠标点击的横坐标
          let offsetY = $el.offsetY; // 鼠标点击的纵坐标
          // 按照比例实际上用户点击的位置,把鼠标点击的位置转换成660 * 260的相应位置
          let userPointX = parseInt((660 * offsetX) / cImgW);
          let userPointY = parseInt((260 * offsetY) / cImgH);
          // this.pointData 是数组格式,切里面的每个对象里还有对象
          let pointDataCopy = JSON.parse(JSON.stringify(this.pointData));
          // 判断画布上有无图形
          if (pointDataCopy.length > 0) {
            let dot = {
              x: userPointX,
              y: userPointY,
            };
    
            pointDataCopy.map((item) => {
              item.maxArray = [];
              item.maxArray.push(item.point1);
              item.maxArray.push(item.point2);
              item.maxArray.push(item.point4);
              item.maxArray.push(item.point3);
              item.maxArray.push(item.point1);
              // maxArray 是多边形点的集合,坐标格式是{x, y}
              let flag = this.judge(dot, item.maxArray);
              // if (flag) {
              //   console.log(item.name);
              // }
            });
          }
        },
    
    /**
         * @param  dot {x,y} 需要判断的点
         * @param  coordinates [{x,y},{x,y}....] 多边形点坐标的数组,为保证图形能够闭合,起点和终点必须相等。这里有个要求,就是点坐标的数组集合的点必须是顺时针或逆时针,如果顺序不一样,无法判断
         *        比如三角形需要四个点表示,第一个点和最后一个点必须相同。
         * @param noneZeroMode 对不规则图形进行判断
         */
        judge(dot, coordinates, noneZeroMode) {
          // 默认启动none zero mode
          noneZeroMode = noneZeroMode || 1;
          var x = dot.x,
            y = dot.y;
          var crossNum = 0;
          // 点在线段的左侧数目
          var leftCount = 0;
          // 点在线段的右侧数目
          var rightCount = 0;
          for (var i = 0; i < coordinates.length - 1; i++) {
            var start = coordinates[i];
            var end = coordinates[i + 1];
    
            // 起点、终点斜率不存在的情况
            if (start.x === end.x) {
              // 因为射线向右水平,此处说明不相交
              if (x > start.x) continue;
    
              // 从左侧贯穿
              if (end.y > start.y && y >= start.y && y <= end.y) {
                leftCount++;
                crossNum++;
              }
              // 从右侧贯穿
              if (end.y < start.y && y >= end.y && y <= start.y) {
                rightCount++;
                crossNum++;
              }
              continue;
            }
            // 斜率存在的情况,计算斜率
            var k = (end.y - start.y) / (end.x - start.x);
            // 交点的x坐标
            var x0 = (y - start.y) / k + start.x;
            // 因为射线向右水平,此处说明不相交
            if (x > x0) continue;
    
            if (end.x > start.x && x0 >= start.x && x0 <= end.x) {
              crossNum++;
              if (k >= 0) leftCount++;
              else rightCount++;
            }
            if (end.x < start.x && x0 >= end.x && x0 <= start.x) {
              crossNum++;
              if (k >= 0) rightCount++;
              else leftCount++;
            }
          }
    
          return noneZeroMode === 1
            ? leftCount - rightCount !== 0
            : crossNum % 2 === 1;
        },
    
    效果

    在这里插入图片描述

    展开全文
  • [地图Map] 关于如何在手机上使用百度地图API画多边形  以 最近有个需求,就是要在手机上利用百度地图一个多边形,然后把多边形的坐标数组传到服务器上。web前端上百度提供了测距工具...
  • 前面在《纯CSS制作的图形效果》一文中介绍了十六种CSS各种不同图形的方法。今天花了点时间将这方面的制作成一份清单,方便大家急用时有地方可查。别的不多说了,直接看代码。为了节省时间,下面图形都采用的一个...
  • 在css-tricks上有一篇文章,居然能只用CSS出这么多基本的图形。图形包括基本的矩形、圆形、椭圆、三角形、多边形,也包括稍微复杂一点的爱心、钻石、阴阳八卦等。当然有一些需要用到CSS3的属性,所以在你打开这篇...
  • 周五下班前师父给我留了个任务,让我周末回家研究研究 iPhone 手机下载 App 时的效果是怎么实现的(不知道效果的童鞋请看下图) 如果所示,下载 App 的过程效果,就是 App 图标中间有一个顺时针旋转的圆圈。当一圈...
  • javascript怎么画正五边形?下面本篇文章给大家介绍一下。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。如何用程序来绘制正多边形?在一般情况下,会使用 x = radius * Math.cos(angle), y = ...
  • 等边三角形,在用CAD怎么画

    千次阅读 2017-07-30 21:55:21
    CAD可用多边形画法,办法如下: 1、正交模式打开(F8) 2、输入命令:POL回车,接着输入3(即三条边)回车; 3、输入E回车,鼠标(左键)指定边的起点; 4、输入边的长度(例如20)回车确认,完成。如图:
  • 多边形的填充

    2015-05-03 08:43:58
    寻找水平线(亦即扫描线)和多边形边界的交点个数,如果交点个数唯一,那么不该点。矩形填充问题一 怎么样描述在矩形内部、外部和在边界上的像素点 解决方案 把轮廓线内的部分分解成水平宽带的集合(扫描线) 通过...
  • 扫描线法填充多边形

    千次阅读 2015-10-20 19:30:52
    原理 如下图所示多边形: 简述 直线y=1,2,3……8...现在考虑直线y=2,它与多边形有3个交点,很显然是F,G之间线,那么p1怎么处理呢?可以观察到p1是多边形边的一个端点,是两条边的交点,因此,可以选择将p1看
  • 而且不能重叠,所以我想用正多边形,正多边形中心点到各点距离相等,且不重叠,,但是正多边形又不能得到中心点。。。。。怎样才能得到中心点??或者有更好的办法可以,而且可以得到直线的终点?
  • 多边形扫描转换算法(C语言实现)

    千次阅读 2020-12-23 17:49:13
    多边形扫描转换算法(C语言实现) 原理不赘述 原理可跳转至该文章 ET边表 ...这几天一直在琢磨怎么实现算法,还是纯C的那种,于是就有下面的代码。 该算法难在ET表和AET表。这里我仅仅用到了ET表,用一
  • 先说hdu4353这道题,题意是要求一个从N个点1里边出一个多边形来,然后给出M个点2。让这个(多边形的面积/多边形内点2的个数)最小。 描述很复杂。。。但是仔细想想会发现,多边形的点越多,面积也就越大,所以,...
  • ![图片说明](https://img-ask.csdn.net/upload/201907/09/1562671422_567068.png) 我已经用DrawLines出的多边形,但不知道怎么在多边区域内填色填色?
  • 起因 ... 在做完例子之后,就想到如果是四个点,五个点,怎么样。 就改写了一下代码,把点的数目变量化。...然后按照角度从小到大的去连接这些点,这样就能出一个正常的多边形了。 大致实现代码如下: let balls = []
  • 大概的看了整个需求,这个活动的难点在于结果页面的六边形指标怎么实现。 效果demo类似 (此图片来源于网络,如有侵权,请联系删除! ) 分析 背景  首先,这是用户对应六个属性值的等边六边形,等边六边形这是一个很...
  • 51Nod-1804-小C的多边形

    2017-05-13 18:38:51
    一开始我了半天 n=5n = 5 的情况,发现怎么找也找不出来可行解。于是尝试 n=6n = 6 的情况,找到了一组可行解 3 5 2 4 13\ 5\ 2\ 4\ 1,然后大胆的猜测,每隔一项差为1,注意取模,并且第二项为最大值,这样,...
  • 在OpenCV-Python教程:绘制直线、圆形、方形一文中介绍了怎么绘制直线、圆形、方形,这里介绍下怎么绘制多边形、输出文字。 1、多边形 cv2.polylines()用来画多边形。 第1个参数为图像对象; 第2个参数为包含一...
  • OpenGL多边形的绘制(多个三角形连接)

    千次阅读 2012-05-31 20:04:23
    上一篇博客介绍怎么画三角形,这篇文章介绍怎么样画连续的三角形。使用图元GL_TRIANGLE_STRIP可以绘制连续的三角形。废话不多说了,直接上代码了。 #include void RenderScene(void) { glClear(GL_COLOR_BUFFER...
  • 接上文 计算机图形学 学习笔记(一):概述,光栅图形学算法:直线扫描算法(DDA,中点线算法,Bresenham算法)光栅图形学算法2.4 多边形扫描转换-X扫描线算法多边形的扫描转换和区域填充这个问题是怎么样在离散的...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 133
精华内容 53
关键字:

多边形怎么画