Skip to content

Commit d7bc89a

Browse files
authored
Merge pull request #10 from lrosemberg/esc-clear-polygon
Adding instructions, ESC and Ctrl-Z functionality and some bug fixes.
2 parents 421c945 + 9038321 commit d7bc89a

File tree

4 files changed

+139
-88
lines changed

4 files changed

+139
-88
lines changed

README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,10 @@ To use PolygonZone, open up the [PolygonZone web application](https://roboflow.g
7878
4. Continue to draw as many polygons as you need.
7979
5. Copy the NumPy array or JSON object that contains the coordinates of the polygons you have drawn.
8080

81-
You can zoom in and out of an image using the mouse wheel or a laptop track pad.
81+
## Functionalities
82+
- You can zoom in and out of an image using the mouse wheel or a laptop track pad.
83+
- You can undo the last point pressing Ctrl/Cmd+Z
84+
- You can discard the last unsaved polygon pressing Esc
8285

8386
## Contributing 🤝
8487

index.html

+22-1
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,35 @@ <h1>Draw points to create polygon coordinates</h1>
3838
</div>
3939
</div>
4040
<div class="right">
41+
<div class="how-to">
42+
<h2>How to use</h2>
43+
<ol class="ta-left">
44+
<li>Drop an image to the indicated area</li>
45+
<li>Select the desired mode: Press <kbd>L</kbd> to draw a line, or <kbd>P</kbd> to draw a polygon</li>
46+
<li>Start creating your polygon, clicking in the desired points of the image</li>
47+
<li>If in polygon mode, press <kbd>ENTER</kbd> to finish the polygon</li>
48+
<li>Repeat steps 2 - 4 as many times as you want</li>
49+
<li>To finish, copy the numpy points to your clipboard</li>
50+
</ol>
51+
</div>
52+
<div class="shortcuts">
53+
<h2>Keyboard shortcuts</h2>
54+
<ul class="ta-left">
55+
<li><kbd>L</kbd>: Switch to line drawing mode</li>
56+
<li><kbd>P</kbd>: Swicth to polygon drawing mode</li>
57+
<li><kbd>Enter</kbd>: If you drawing a polygon, end the polygon</li>
58+
<li><kbd>Esc</kbd>: When drawing, clear the current polygon</li>
59+
<li><kbd>Ctrl(Cmd)-Z</kbd>: Undo the last point</li>
60+
</ul>
61+
</div>
4162
<h2>NumPy Points</h2>
4263
<p>Copy the points below into your Python code.</p>
4364
<a href="" id="clipboard" class="widgetButton">Copy Python to Clipboard</a>
4465
<pre id="python">
4566
<code>
4667
</code>
4768
</pre>
48-
<div class="show_normalized" style="margin-bottom: 25px;">
69+
<div class="show_normalized mb-3">
4970
<label for="normalize_checkbox">Show Normalized Points from 0-1</label>
5071
<input type="checkbox" id="normalize_checkbox" name="normalize_checkbox" value="normalize_checkbox">
5172
</div>

script.js

+92-86
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,50 @@ function getScaledCoords(e) {
9191
return [x / scaleFactor, y / scaleFactor];
9292
}
9393

94+
function drawCurrentPolygon (cursorX, cursorY) {
95+
//ctx.clearRect(0, 0, canvas.width, canvas.height);
96+
ctx.drawImage(img, 0, 0);
97+
for (var i = 0; i < points.length - 1; i++) {
98+
// draw arc around each point
99+
ctx.beginPath();
100+
ctx.strokeStyle = rgb_color;
101+
ctx.arc(points[i][0], points[i][1], 5, 0, 2 * Math.PI);
102+
// fill with white
103+
ctx.fillStyle = 'white';
104+
ctx.fill();
105+
ctx.stroke();
106+
drawLine(points[i][0], points[i][1], points[i + 1][0], points[i + 1][1]);
107+
}
108+
109+
if ((points.length > 0 && drawMode == "polygon") || (points.length > 0 && points.length < 2 && drawMode == "line")) {
110+
ctx.beginPath();
111+
ctx.strokeStyle = rgb_color;
112+
ctx.arc(points[i][0], points[i][1], 5, 0, 2 * Math.PI);
113+
// fill with white
114+
ctx.fillStyle = 'white';
115+
ctx.fill();
116+
ctx.stroke();
117+
118+
if (cursorX && cursorY) {
119+
drawLine(points[points.length - 1][0], points[points.length - 1][1], cursorX, cursorY);
120+
}
121+
122+
if (points.length == 2 && drawMode == "line") {
123+
console.log("line");
124+
// draw arc around each point
125+
ctx.beginPath();
126+
ctx.strokeStyle = rgb_color;
127+
ctx.arc(points[0][0], points[0][1], 5, 0, 2 * Math.PI);
128+
// fill with white
129+
ctx.fillStyle = 'white';
130+
ctx.fill();
131+
ctx.stroke();
132+
masterPoints.push(points);
133+
points = [];
134+
}
135+
}
136+
}
137+
94138
function drawAllPolygons () {
95139
// draw all points for previous regions
96140
for (var i = 0; i < masterPoints.length; i++) {
@@ -124,6 +168,15 @@ function drawAllPolygons () {
124168
}
125169
}
126170

171+
function getParentPoints () {
172+
var parentPoints = [];
173+
for (var i = 0; i < masterPoints.length; i++) {
174+
parentPoints.push(masterPoints[i]);
175+
}
176+
parentPoints.push(points);
177+
return parentPoints;
178+
}
179+
127180
function clearall() {
128181
ctx.clearRect(0, 0, canvas.width, canvas.height);
129182
ctx.drawImage(img, 0, 0);
@@ -180,83 +233,25 @@ canvas.addEventListener('mousemove', function(e) {
180233
ycoord.innerHTML = y;
181234

182235
if (canvas.style.cursor == 'crosshair') {
183-
//ctx.clearRect(0, 0, canvas.width, canvas.height);
184-
ctx.drawImage(img, 0, 0);
185-
for (var i = 0; i < points.length - 1; i++) {
186-
// draw arc around each point
187-
ctx.beginPath();
188-
ctx.strokeStyle = rgb_color;
189-
ctx.arc(points[i][0], points[i][1], 5, 0, 2 * Math.PI);
190-
// fill with white
191-
ctx.fillStyle = 'white';
192-
ctx.fill();
193-
ctx.stroke();
194-
drawLine(points[i][0], points[i][1], points[i + 1][0], points[i + 1][1]);
195-
}
196-
if ((points.length > 0 && drawMode == "polygon") || (points.length > 0 && points.length < 2 && drawMode == "line")) {
197-
ctx.beginPath();
198-
ctx.strokeStyle = rgb_color;
199-
ctx.arc(points[i][0], points[i][1], 5, 0, 2 * Math.PI);
200-
// fill with white
201-
ctx.fillStyle = 'white';
202-
ctx.fill();
203-
ctx.stroke();
204-
drawLine(points[points.length - 1][0], points[points.length - 1][1], x, y);
205-
206-
if (points.length == 2 && drawMode == "line") {
207-
console.log("line");
208-
// draw arc around each point
209-
ctx.beginPath();
210-
ctx.strokeStyle = rgb_color;
211-
ctx.arc(points[0][0], points[0][1], 5, 0, 2 * Math.PI);
212-
// fill with white
213-
ctx.fillStyle = 'white';
214-
ctx.fill();
215-
ctx.stroke();
216-
masterPoints.push(points);
217-
points = [];
218-
}
219-
}
220-
var parentPoints = [];
221-
222-
for (var i = 0; i < masterPoints.length; i++) {
223-
parentPoints.push(masterPoints[i]);
224-
}
225-
parentPoints.push(points);
226-
236+
drawCurrentPolygon(x, y)
227237
drawAllPolygons();
228238
}
229239
});
230240

241+
242+
231243
window.addEventListener('keydown', function(e) {
244+
e.stopImmediatePropagation()
245+
let validKey = false
246+
232247
if (e.key === 'Enter') {
248+
validKey = true
233249
canvas.style.cursor = 'default';
234-
// remove line drawn by mouseover
235-
// ctx.clearRect(0, 0, canvas.width, canvas.height);
236-
// join the dots
237-
drawLine(points[0][0], points[0][1], points[points.length - 1][0], points[points.length - 1][1]);
238-
// fill polygon with color
239-
if (drawMode == 'polygon') {
240-
ctx.beginPath();
241-
ctx.moveTo(points[0][0], points[0][1]);
242-
ctx.fillStyle = opaque_color;
243-
for (var i = 1; i < points.length; i++) {
244-
ctx.lineTo(points[i][0], points[i][1]);
245-
}
246-
ctx.closePath();
247-
ctx.fill();
248-
// draw line connecting last two points
249-
}
250+
251+
// save current polygon points
250252
masterPoints.push(points);
251-
// draw arc around last point
252-
ctx.beginPath();
253-
ctx.strokeStyle = rgb_color;
254-
ctx.arc(points[points.length - 1][0], points[points.length - 1][1], 5, 0, 2 * Math.PI);
255-
// fill with white
256-
ctx.fillStyle = 'white';
257-
ctx.fill();
258-
ctx.stroke();
259253
points = [];
254+
260255
// dont choose a color that has already been chosen
261256
var remaining_choices = color_choices.filter(function(x) {
262257
return !masterColors.includes(x);
@@ -267,9 +262,25 @@ window.addEventListener('keydown', function(e) {
267262
}
268263

269264
rgb_color = remaining_choices[Math.floor(Math.random() * remaining_choices.length)];
270-
271265
masterColors.push(rgb_color);
272266
}
267+
268+
if (e.key === 'Escape') {
269+
validKey = true
270+
points = []
271+
}
272+
273+
if (e.key === 'z' && (e.ctrlKey || e.metaKey)) {
274+
validKey = true
275+
points.pop()
276+
}
277+
278+
if (validKey) {
279+
drawCurrentPolygon()
280+
drawAllPolygons();
281+
var parentPoints = getParentPoints();
282+
writePoints(parentPoints);
283+
}
273284
});
274285

275286
canvas.addEventListener('drop', function(e) {
@@ -327,6 +338,15 @@ function writePoints(parentPoints) {
327338
parentPoints = normalized;
328339
}
329340

341+
// clean empty points
342+
parentPoints = parentPoints.filter(points => !!points.length);
343+
344+
if (!parentPoints.length) {
345+
document.querySelector('#python').innerHTML = '';
346+
document.querySelector('#json').innerHTML;
347+
return;
348+
}
349+
330350
// create np.array list
331351
var code_template = `
332352
[
@@ -339,6 +359,7 @@ ${points.map(function(point) {
339359
}).join(',')}
340360
]
341361
`;
362+
342363
document.querySelector('#python').innerHTML = code_template;
343364

344365
var json_template = `
@@ -378,28 +399,13 @@ canvas.addEventListener('click', function(e) {
378399
}
379400

380401
ctx.arc(x, y, 155, 0, 2 * Math.PI);
381-
// concat all points into one array
382-
var parentPoints = [];
383-
384-
for (var i = 0; i < masterPoints.length; i++) {
385-
parentPoints.push(masterPoints[i]);
386-
}
387-
// add "points"
388-
parentPoints.push(points);
389402

403+
var parentPoints = getParentPoints();
390404
writePoints(parentPoints);
391405
});
392406

393407
document.querySelector('#normalize_checkbox').addEventListener('change', function(e) {
394408
showNormalized = e.target.checked;
395-
// normalize all
396-
var parentPoints = [];
397-
398-
for (var i = 0; i < masterPoints.length; i++) {
399-
parentPoints.push(masterPoints[i]);
400-
}
401-
402-
parentPoints.push(points);
403-
409+
var parentPoints = getParentPoints();
404410
writePoints(parentPoints);
405411
});

styles.css

+21
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,24 @@ pre {
167167
footer {
168168
margin-top: 20px;
169169
}
170+
171+
li {
172+
margin-bottom: 4px;
173+
}
174+
175+
/* Helpers */
176+
.ta-left {
177+
text-align: left;
178+
}
179+
180+
.mb-1 {
181+
margin-bottom: 8px;
182+
}
183+
184+
.mb-2 {
185+
margin-bottom: 16px;
186+
}
187+
188+
.mb-3 {
189+
margin-bottom: 24px;
190+
}

0 commit comments

Comments
 (0)