{"id":484,"date":"2021-07-03T11:09:12","date_gmt":"2021-07-03T03:09:12","guid":{"rendered":"https:\/\/swordofmorning.com\/?p=484"},"modified":"2025-10-09T13:55:52","modified_gmt":"2025-10-09T05:55:52","slug":"swust-computer-graphics-experiment-2-drawing-interactive-polygons","status":"publish","type":"post","link":"https:\/\/swordofmorning.com\/index.php\/2021\/07\/03\/swust-computer-graphics-experiment-2-drawing-interactive-polygons\/","title":{"rendered":"SWUST \u8ba1\u7b97\u673a\u56fe\u5f62\u5b66 \u5b9e\u9a8c\u4e8c \u7ed8\u5236\u4ea4\u4e92\u5f0f\u591a\u8fb9\u5f62"},"content":{"rendered":"<p><div class=\"has-toc have-toc\"><\/div><\/p>\n<h2>\u4e00\u3001\u591a\u8fb9\u5f62\u5206\u5272\u6210\u4e09\u89d2\u5f62<\/h2>\n<p>&emsp;&emsp;\u8fd9\u91cc\u6211\u4eec\u76f4\u63a5\u4f7f\u7528\u7b2c\u4e09\u65b9\u5e93\uff1a<\/p>\n<ol>\n<li>&emsp;&emsp;<a href=\"https:\/\/www.flipcode.com\/archives\/Efficient_Polygon_Triangulation.shtml\" title=\"Efficient Polygon Triangulation\" target=\"_blank\"  rel=\"nofollow\" >Efficient Polygon Triangulation<\/a>\uff0c\u8fdb\u5165\u590d\u5236\u6e90\u4ee3\u7801\u5373\u53ef\u4f7f\u7528\u3002<\/li>\n<li>&emsp;&emsp;<a href=\"http:\/\/www.cs.man.ac.uk\/~toby\/alan\/software\/\/\" title=\"GPC \u2013 General Polygon Clipper library\" target=\"_blank\"  rel=\"nofollow\" >GPC \u2013 General Polygon Clipper library<\/a>\uff0c\u5f88\u9057\u61be\u8fd9\u4e2a\u9879\u76ee\u572820\u5e748\u6708\u505c\u6b62\u4e86\u652f\u6301\uff0c\u8fd8\u662f\u5f88\u4e13\u4e1a\u7684\u4e00\u4e2a\u56fe\u5f62\u5206\u5272\u9879\u76ee\uff0c\u53ef\u4ee5\u81ea\u884c\u67e5\u627e\u662f\u5426\u8fd8\u6709\u53ef\u4ee5\u6e90\u7801\u3002<\/li>\n<\/ol>\n<p>&emsp;&emsp;EPT\u65b9\u6cd5\uff1a<br \/>\n&emsp;&emsp;\u51fd\u6570\u6309\u987a\u65f6\u9488\u53d63\u4e2a\u70b9\u5224\u65ad\u662f\u5426\u4e3a\u51f8\u89d2\uff08\u540c\u65f6\u5176\u4ed6\u70b9\u4e0d\u5f97\u5728\u5176\u5185\uff09\uff0c\u5982\u679c\u6761\u4ef6\u6ee1\u8db3\u5219\u53bb\u6389\u8fd9\u4e09\u70b9\u4e2d\u7684\u4e2d\u95f4\u70b9\uff0c\u5207\u9664\u51fa\u4e00\u4e2a\u4e09\u89d2\u5f62\uff0c\u5269\u4e0b\u591a\u8fb9\u5f62\u7ee7\u7eed\u5207\u5272\u76f4\u5230\u5b8c\u6210\u3002<\/p>\n<ol>\n<li>&emsp;&emsp;rea\u51fd\u6570\uff1a\u8ba1\u7b97\u591a\u8fb9\u5f62\u9762\u79ef\u3002\u5982\u679c\u8ba1\u7b97\u7684\u591a\u8fb9\u5f62\u9762\u79ef\u662f\u8d1f\u7684\u5219\u8bf4\u660e\u662f\u9006\u65f6\u9488\u53d6\u70b9\u3002<\/li>\n<li>&emsp;&emsp;InsideTriangle\u51fd\u6570\uff1a\u5224\u65adP\u662f\u5426\u5728ABC\u4e09\u89d2\u5f62\u5185\uff08\u7528\u7684\u5411\u91cf\u5dee\u79ef\u6cd5\uff0c\u5176\u5b9e\u4e5f\u662f\u9762\u79ef\u6cd5\uff09\u3002<\/li>\n<li>&emsp;&emsp;Snip\u51fd\u6570\uff1a\u5224\u65ad\u4e09\u70b9\u6761\u4ef6\u3002<\/li>\n<li>&emsp;&emsp;Process\u5207\u5272\u51fd\u6570\uff0c\u5f53snip\u6ee1\u8db3\u65f6\uff0c\u53bb\u9664\u4e00\u4e2a\u70b9\uff0c\u7ed9\u591a\u8fb9\u5f62\u91cd\u65b0\u7f16\u53f7\uff0c\u53d6\u70b9\u5411\u540e\u79fb2\u4f4d\u3002<\/li>\n<\/ol>\n<h2>\u4e8c\u3001\u5b9e\u9a8c\u8981\u6c42<\/h2>\n<p>&emsp;&emsp;\uff081\uff09\u4f7f\u7528\u9f20\u6807\u5728\u5c4f\u5e55\u5ba2\u6237\u533a\u7ed8\u5236\u4efb\u610f\u70b9\u6570\u7684\u591a\u8fb9\u5f62\u3002\u8981\u6c42\u4f7f\u7528\u6a61\u76ae\u7b4b\u6280\u672f \u52a8\u6001\u7ed8\u5236\u6bcf\u6761\u8fb9\uff1b\u9f20\u6807\u79fb\u52a8\u8fc7\u7a0b\u4e2d\u6309\u4e0b Shi \u952e\u65f6\u53ef\u7ed8\u5236\u5782\u76f4\u8fb9\u6216\u6c34\u5e73\u8fb9\uff1b\u5c06\u591a \u8fb9\u5f62\u7684\u7ec8\u70b9\u79fb\u52a8\u5230\u591a\u8fb9\u5f62\u7684\u8d77\u70b9\u65f6\u81ea\u52a8\u5c01\u95ed\u591a\u8fb9\u5f62\uff1b\u5728\u7ed8\u5236\u591a\u8fb9\u5f62\u7684\u8fc7\u7a0b\u4e2d\uff0c\u72b6 \u6001\u680f\u52a8\u6001\u663e\u793a\u9f20\u6807\u5149\u6807\u7684\u4f4d\u7f6e\u5750\u6807\u3002<br \/>\n&emsp;&emsp;\uff082\uff09\u5f53\u5f00\u59cb\u7ed8\u5236\u591a\u8fb9\u5f62\u65f6\uff0c\u66f4\u6539\u9f20\u6807\u5149\u6807\u4e3a\u5341\u5b57\u5149\u6807\uff0c\u591a\u8fb9\u5f62\u7ed8\u5236\u5b8c\u6bd5\u540e \u6062\u590d\u4e3a\u7bad\u5934\u5149\u6807\u3002<br \/>\n&emsp;&emsp;\uff083\uff09\u591a\u8fb9\u5f62\u95ed\u5408\u540e\u81ea\u52a8\u8c03\u7528\u6709\u6548\u8fb9\u8868\u7b97\u6cd5\u586b\u5145\u591a\u8fb9\u5f62\u5185\u90e8\u533a\u57df\u3002<\/p>\n<h2>\u4e09\u3001\u6e90\u7801\uff08\u4f7f\u7528EPT\u5b8c\u6210\uff09<\/h2>\n<pre><code class=\"language-cpp\">#include &lt;iostream&gt;\n#include &lt;GL\/glut.h&gt;\n#include &lt;glm\/glm.hpp&gt;\n#include &lt;vector&gt;\n#include &quot;triangulate.h&quot;\n\n\/*---\u5e38\u91cf---*\/\nconst int HEIGHT(800);\nconst int WIDTH(800);\n\n\/*---\u5168\u5c40\u53d8\u91cf---*\/\nglm::vec2 StartPoint{ 0, 0 };\nglm::vec2 EndPoint{ 0, 0 };\n\/\/\u7ed8\u7ebf\u53d8\u91cf\nstd::vector&lt;glm::vec2&gt; VertexArray;\n\/\/\u9876\u70b9\u6570\u7ec4\n\n\/*---\u51fd\u6570---*\/\nvoid Display();                                 \/\/mian\u4e2d\u663e\u793a\u5b50\u7a0b\u5e8f\nvoid Reshape(int, int);                         \/\/\u6295\u5f71\u53d8\u6362\u51fd\u6570\nvoid MouseMove(int, int);                       \/\/\u9f20\u6807\u79fb\u52a8\u4e8b\u4ef6\nvoid MouseClick(int, int, int, int);            \/\/\u9f20\u6807\u70b9\u51fb\u4e8b\u4ef6\nvoid DrawLine(int, int);                        \/\/\u7ed8\u5236\u76f4\u7ebf\nvoid DrawEdge();                                \/\/\u7ed8\u5236\u591a\u8fb9\u5f62\u7684\u8fb9\nvoid DrawPolygon();                             \/\/\u7ed8\u5236\u591a\u8fb9\u5f62\nVector2dVector PolygonToTriangle();             \/\/\u526a\u88c1\u591a\u8fb9\u5f62\n\nint main(int argc, char** argv)\n{\n    glutInit(&amp;argc, argv);\n    \/\/GLUT\u521d\u59cb\u5316\n\n    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);\n    \/\/\u53cc\u7f13\u5b58\u6a21\u5f0f\n\n    glutInitWindowSize(WIDTH, HEIGHT);\n    glutInitWindowPosition(50, 100);\n    \/\/\u7a97\u53e3\u521d\u59cb\u5316\n\n    glClearColor(0, 0, 0, 1);\n    \/\/\u7a97\u53e3\u989c\u8272\n\n    glutCreateWindow(&quot;Draw and Filled Ploygon&quot;);\n\n    glutDisplayFunc(Display);\n    glutMouseFunc(MouseClick);\n    glutReshapeFunc(Reshape);\n\n    glutMainLoop();\n}\n\nvoid Display()\n{\n    glClear(GL_COLOR_BUFFER_BIT);\n}\n\nvoid Reshape(int w, int h)\n{\n    glMatrixMode(GL_PROJECTION);\n    glLoadIdentity();\n    gluOrtho2D(0, WIDTH, 0, HEIGHT);\n}\n\nvoid MouseMove(int x, int y)\n{\n    std::cout &lt;&lt; &quot;(&quot; &lt;&lt; x &lt;&lt; &quot;, &quot; &lt;&lt; y &lt;&lt; &quot;)&quot; &lt;&lt; std::endl;\n\n    int slope = ((y - StartPoint.y) \/ (x - StartPoint.x));\n    \/\/\u659c\u7387\n    int Shift = glutGetModifiers();\n    \/\/\u83b7\u53d6\u7279\u6b8a\u6309\u952e\n    glm::vec2 GoalPoint{ 0,0 };\n    if (GLUT_ACTIVE_SHIFT == Shift)\n    {\n        if (slope == 1)                     \/\/\u659c\u7387\u4e3a1, \u7ed8\u5236 45\u00b0\u659c\u7ebf\n        {\n            GoalPoint.x = x;\n            GoalPoint.y = (HEIGHT - x);\n        }\n        else if (slope == -1)               \/\/\u659c\u7387\u4e3a-1, \u7ed8\u5236 -45\u00b0\u659c\u7ebf\n        {\n            GoalPoint.x = x;\n            GoalPoint.y = x;\n        }\n        else if ((slope &gt; -1) &amp;&amp; (slope &lt; 1))   \/\/\u659c\u7387\u5728-1\u52301\u4e4b\u95f4, \u7ed8\u5236 x \u65b9\u5411\u5e73\u884c\u7ebf\n        {\n            GoalPoint.x = x;\n            GoalPoint.y = StartPoint.y;\n        }\n        else if ((slope &lt; -1) || (slope &gt; 1))   \/\/\u659c\u7387\u5c0f\u4e8e-1 \u6216 \u5927\u4e8e1, \u7ed8\u5236 y \u65b9\u5411\u5e73\u884c\u7ebf\n        {\n            GoalPoint.x = StartPoint.x;\n            GoalPoint.y = (HEIGHT - y);\n        }\n    }\n    else if (GLUT_ACTIVE_SHIFT != Shift)\n    {\n        GoalPoint.x = x;\n        GoalPoint.y = (HEIGHT - y);\n    }\n    DrawLine(GoalPoint.x, GoalPoint.y);\n}\n\nvoid MouseClick(int button, int state, int x, int y)\n{\n    if (GLUT_DOWN == state &amp;&amp; GLUT_LEFT_BUTTON == button)\n    {\n        \/\/\u5de6\u952e\u6309\u4e0b\uff1a\u52a8\u6001\u753b\u7ebf\n        if (VertexArray.empty())\n        {\n            StartPoint.x = x;\n            StartPoint.y = (HEIGHT - y);\n            VertexArray.push_back(StartPoint);\n        }\n        \/\/\u6570\u7ec4\u7a7a\uff1a\u65b0\u5efa\u9876\u70b9\u5b58\u5165\u6570\u7ec4\uff0c\u5426\u5219\u76f4\u63a5\u4ee5\u591a\u8fb9\u5f62\u6700\u540e\u4e00\u4e2a\u70b9\u4f5c\u4e3a\u9876\u70b9\n\n        StartPoint.x = VertexArray.back().x;\n        StartPoint.y = VertexArray.back().y;\n        glutMotionFunc(MouseMove);\n    }\n    else if (GLUT_UP == state &amp;&amp; GLUT_LEFT_BUTTON == button)\n    {\n        int Shift = glutGetModifiers();\n        int slope = ((y - StartPoint.y) \/ (x - StartPoint.x));\n        if (GLUT_ACTIVE_SHIFT == Shift)\n        {\n            if (slope == 1)                     \/\/\u659c\u7387\u4e3a1, \u7ed8\u5236 45\u00b0\u659c\u7ebf\n            {\n                EndPoint.x = x;\n                EndPoint.y = (HEIGHT - x);\n            }\n            else if (slope == -1)               \/\/\u659c\u7387\u4e3a-1, \u7ed8\u5236 -45\u00b0\u659c\u7ebf\n            {\n                EndPoint.x = x;\n                EndPoint.y = x;\n            }\n            else if ((slope &gt; -1) &amp;&amp; (slope &lt; 1))   \/\/\u659c\u7387\u5728-1\u52301\u4e4b\u95f4, \u7ed8\u5236 x \u65b9\u5411\u5e73\u884c\u7ebf\n            {\n                EndPoint.x = x;\n                EndPoint.y = StartPoint.y;\n            }\n            else if ((slope &lt; -1) || (slope &gt; 1))   \/\/\u659c\u7387\u5c0f\u4e8e-1 \u6216 \u5927\u4e8e1, \u7ed8\u5236 y \u65b9\u5411\u5e73\u884c\u7ebf\n            {\n                EndPoint.x = StartPoint.x;\n                EndPoint.y = (HEIGHT - y);\n            }\n        }\n        else if (GLUT_ACTIVE_SHIFT != Shift)\n        {\n            EndPoint.x = x;\n            EndPoint.y = (HEIGHT - y);\n        }\n        VertexArray.push_back(EndPoint);\n        \/\/\u7ec8\u70b9\u5b58\u5165\n\n        StartPoint = glm::vec2{ 0,0 };\n        EndPoint = glm::vec2{ 0,0 };\n        \/\/Clear\n\n        DrawEdge();\n    }\n    else if (GLUT_DOWN == state &amp;&amp; GLUT_RIGHT_BUTTON == button)\n    {\n        \/\/\u53f3\u952e\u628a\u7ebf\u6bb5\u8f6c\u6362\u4e3a\u591a\u8fb9\u5f62\n        DrawPolygon();\n    }\n}\n\nvoid DrawLine(int x, int y)\n{\n    DrawEdge();\n\n    glColor3f(0, 1.0, 1.0);\n    \/\/\u989c\u8272\u9009\u62e9cyan\n\n    glClear(GL_COLOR_BUFFER_BIT);\n    \/\/\u5237\u65b0\u7f13\u51b2\u533a\n\n    glLineWidth(1);\n    \/\/\u7ebf\u6761\u5bbd\u5ea6\uff1a1\u4e2a\u50cf\u7d20\n\n    glBegin(GL_LINES);\n    glVertex2i(StartPoint.x, StartPoint.y);\n    glVertex2i(x, y);\n    glEnd();\n    \/\/\u753b\u7ebf\n\n    glutSwapBuffers();\n}\n\nvoid DrawEdge()\n{\n    glColor3f(0, 1.0, 1.0);\n    glClear(GL_COLOR_BUFFER_BIT);\n    glLineWidth(1);\n    \/\/\u57fa\u672c\u8bbe\u7f6e\u540c\u4e0a\n\n    glBegin(GL_LINE_STRIP);\n    for (auto i : VertexArray)\n    {\n        glVertex2i(i.x, i.y);\n    }\n    glEnd();\n    \/\/\u753b\u56fe\n\n    glutSwapBuffers();\n}\n\nvoid DrawPolygon()\n{\n    glColor3f(0, 0.5, 1.0);\n    glClear(GL_COLOR_BUFFER_BIT);\n    glLineWidth(1);\n    \/\/\u57fa\u672c\u8bbe\u7f6e\u540c\u4e0a\n\n    Vector2dVector TriangleVertexArray = PolygonToTriangle();\n\n    glBegin(GL_TRIANGLES);\n    for (auto i : TriangleVertexArray)\n    {\n        glVertex2i(i.GetX(), i.GetY());\n    }\n    glEnd();\n    \/\/\u753b\u56fe\n\n    glutSwapBuffers();\n}\n\nVector2dVector PolygonToTriangle()\n{\n    Vector2dVector PolygonVertexArray;\n    Vector2dVector TriangleVertexArray;\n    for (auto i : VertexArray)\n    {\n        Vector2d TheVertex(i.x, i.y);\n        PolygonVertexArray.push_back(TheVertex);\n    }\n\n    Triangulate::Process(PolygonVertexArray, TriangleVertexArray);\n\n    return TriangleVertexArray;\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u4e00\u3001\u591a\u8fb9\u5f62\u5206\u5272\u6210\u4e09\u89d2\u5f62 &emsp;&emsp;\u8fd9\u91cc\u6211\u4eec\u76f4\u63a5\u4f7f\u7528\u7b2c\u4e09\u65b9\u5e93\uff1a &emsp;&emsp;Efficient Polyg &#8230;<\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[62],"tags":[238,237],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/posts\/484"}],"collection":[{"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/comments?post=484"}],"version-history":[{"count":1,"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/posts\/484\/revisions"}],"predecessor-version":[{"id":485,"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/posts\/484\/revisions\/485"}],"wp:attachment":[{"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/media?parent=484"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/categories?post=484"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/tags?post=484"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}