2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 module ybdecomposer_sample
;
19 import arsd
.simpledisplay
;
24 import iv
.vmath2d
.math2d
;
25 import iv
.vmath2d
.vxstore
;
26 static import iv
.vmath2d
.creatori
; // hello, rdmd
27 import iv
.vmath2d
.ybdecomposer
;
31 enum winHeight
= 1024;
32 VertexStorage
!vec2 incPoly
;
33 VertexStorage
!vec2
[] polys
;
35 bool polyComplete
= false;
36 vec2 splitA
= vec2
.Invalid
, splitB
= vec2
.Invalid
;
39 void glColor1i(int c
, ubyte a
) {
40 glColor4ub((c
>> 16) & 0xff, (c
>> 8) & 0xff, c
& 0xff, a
);
45 //srand((unsigned) time(0));
46 uint[$] colors
= [0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff, 0x00ffff, 0xff8800];
48 auto sdwin
= new SimpleWindow(winWidth
, winHeight
, "polytest", OpenGlOptions
.yes
);
50 sdwin
.visibleForTheFirstTime
= delegate () {
53 sdwin
.setAsCurrentOpenGlContext();
54 oglSetup2D(winWidth
, winHeight
);
58 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
59 glEnable(GL_LINE_SMOOTH
);
60 glEnable(GL_POINT_SMOOTH
);
63 sdwin
.redrawOpenGlScene
= delegate () {
66 oglSetup2D(winWidth
, winHeight
);
70 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
71 glEnable(GL_LINE_SMOOTH
);
72 glEnable(GL_POINT_SMOOTH
);
75 glClear(GL_COLOR_BUFFER_BIT
);
78 if (incPoly
.length
> 0) {
83 glBegin(GL_LINE_STRIP
);
84 for (int i
= 0; i
< incPoly
.length
; ++i
) {
85 glVertex2f(incPoly
[i
].x
, incPoly
[i
].y
);
90 for (int i
= 0; i
< incPoly
.length
; ++i
) {
91 glVertex2f(incPoly
[i
].x
, incPoly
[i
].y
);
97 glColor4f(1, 1, 1, .5);
99 glVertex2f(incPoly
[-1].x
, incPoly
[-1].y
);
100 glVertex2f(mouseX
, mouseY
);
105 for (int i
= 0; i
< polys
.length
; ++i
) {
106 glColor1i(colors
[i
% colors
.length
], 64);
108 for (int j
= 0; j
< polys
[i
].length
; ++j
) {
109 glVertex2f(polys
[i
][j
].x
, polys
[i
][j
].y
);
114 // polygon outlines (thin)
115 for (int i
= 0; i
< polys
.length
; ++i
) {
118 glBegin(GL_LINE_LOOP
);
119 for (int j
= 0; j
< polys
[i
].length
; ++j
) {
120 glVertex2f(polys
[i
][j
].x
, polys
[i
][j
].y
);
125 // original polygon and points
130 glBegin(GL_LINE_LOOP
);
131 for (int i
= 0; i
< incPoly
.length
; ++i
) {
132 glVertex2f(incPoly
[i
].x
, incPoly
[i
].y
);
137 for (int i
= 0; i
< incPoly
.length
; ++i
) {
138 glVertex2f(incPoly
[i
].x
, incPoly
[i
].y
);
149 glVertex2f(splitA
.x
, splitA
.y
);
150 if (splitB
.valid
) glVertex2f(splitB
.x
, splitB
.y
); else glVertex2f(mouseX
, mouseY
);
155 //sdwin.redrawOpenGlSceneNow();
156 sdwin
.eventLoop(1000/30,
158 sdwin
.redrawOpenGlSceneNow();
160 delegate (KeyEvent event
) {
161 if (!event
.pressed
) return;
162 if (event
== "Escape" || event
== "C-Q") { sdwin
.close(); return; }
163 if (event
== "C-C") {
166 polyComplete
= false;
167 //steinerPoints = null;
168 //reflexVertices = null;
173 YBDecomposer
!vec2
.convexPartition(polys
, incPoly
);
174 writeln("generated ", polys
.length
, " polygon", (polys
.length
!= 1 ?
"s" : ""));
178 import iv
.vmath2d
.creatori
;
181 ellipse(incPoly
, 50, 110, 20);
182 incPoly
.moveTo(vec2(winWidth
/2, winHeight
/2));
187 import iv
.vmath2d
.creatori
;
190 roundedRect(incPoly
, 110, 70, 10, 10, 6);
191 incPoly
.moveTo(vec2(winWidth
/2, winHeight
/2));
196 import iv
.vmath2d
.creatori
;
199 capsule(incPoly
, 110, 20, 6);
200 incPoly
.moveTo(vec2(winWidth
/2, winHeight
/2));
205 import iv
.vmath2d
.creatori
;
208 gear(incPoly
, 100, 8, 90, 18);
209 incPoly
.moveTo(vec2(winWidth
/2, winHeight
/2));
214 delegate (MouseEvent event
) {
217 if (event
.type
== MouseEventType
.buttonPressed
&& event
.button
== MouseButton
.left
) {
219 if (incPoly
.length
< 3 ||
vec2(mouseX
, mouseY
).distanceSquared(incPoly
[0]) > 100) {
220 incPoly
~= vec2(mouseX
, mouseY
);
224 if (event
.type
== MouseEventType
.buttonPressed
&& event
.button
== MouseButton
.right
) {
227 YBDecomposer
!vec2
.convexPartition(polys
, incPoly
);
228 writeln("generated ", polys
.length
, " polygon", (polys
.length
!= 1 ?
"s" : ""));
230 if (event
.type
== MouseEventType
.buttonPressed
&& event
.button
== MouseButton
.middle
) {
232 splitA
= vec2(mouseX
, mouseY
);
233 } else if (!splitB
.valid
) {
234 splitB
= vec2(mouseX
, mouseY
);
238 VertexStorage!vec2[] pp;
239 foreach (ref px; polys) {
240 auto first = Creatori!vec2.split(px, splitA, splitB);
241 if (first.length) pp ~= first;
242 if (px.length) pp ~= px;
246 splitA
= vec2
.Invalid
;
247 splitB
= vec2
.Invalid
;