Załaduj obraz do tego fragmentu stosu i przesuń nad nim kursor myszy. Narysowana zostanie czarna krzywa, która podąża za kątem barwy , zaczynając od punktu kursora:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><style>canvas{border:1px solid black;}</style>Load an image: <input type='file' onchange='load(this)'><br><br>Max length <input id='length' type='text' value='300'><br><br><div id='coords'></div><br><canvas id='c' width='100' height='100'>Your browser doesn't support the HTML5 canvas tag.</canvas><script>function load(t){if(t.files&&t.files[0]){var e=new FileReader;e.onload=setupImage,e.readAsDataURL(t.files[0])}}function setupImage(t){function e(t){t.attr("width",img.width),t.attr("height",img.height);var e=t[0].getContext("2d");return e.drawImage(img,0,0),e}img=$("<img>").attr("src",t.target.result)[0],ctx=e($("#c")),ctxRead=e($("<canvas>"))}function findPos(t){var e=0,a=0;if(t.offsetParent){do e+=t.offsetLeft,a+=t.offsetTop;while(t=t.offsetParent);return{x:e,y:a}}return void 0}$("#c").mousemove(function(t){function e(t,e){var a=ctxRead.getImageData(t,e,1,1).data,i=a[0]/255,r=a[1]/255,o=a[2]/255;return Math.atan2(Math.sqrt(3)*(r-o),2*i-r-o)}if("undefined"!=typeof img){var a=findPos(this),i=t.pageX-a.x,r=t.pageY-a.y;$("#coords").html("x = "+i.toString()+", y = "+r.toString());var o=parseInt($("#length").val());if(isNaN(o))return void alert("Bad max length!");for(var n=[i],f=[r],h=0;n[h]>=0&&n[h]<this.width&&f[h]>=0&&f[h]<this.height&&o>h;)n.push(n[h]+Math.cos(e(n[h],f[h]))),f.push(f[h]-Math.sin(e(n[h],f[h]))),h++;ctx.clearRect(0,0,this.width,this.height),ctx.drawImage(img,0,0);for(var h=0;h<n.length;h++)ctx.fillRect(Math.floor(n[h]),Math.floor(f[h]),1,1)}});</script>
Ten fragment kodu przetestowałem tylko w Google Chrome.
Na przykład, gdy kursor znajduje się powyżej czerwonego, krzywa ma nachylenie 0 °, ale gdy jest powyżej żółtego, ma nachylenie 60 °. Krzywa jest kontynuowana dla określonej długości, stale zmieniając jej nachylenie, aby dopasować do odcienia.
Załaduj ten obraz, a kiedy przesuniesz na nim kursor, linia wokół kursora powinna wykonać pełny obrót w lewo:
To i to inne fajne obrazy do wypróbowania. (Musisz je zapisać, a następnie załadować za pomocą fragmentu. Nie można ich bezpośrednio połączyć z powodu ograniczeń krzyżowych.)
Oto niezamknięta wersja fragmentu:
Wyzwanie
Napisz program, który robi to, co robi fragment kodu, ale nie interaktywnie. Zrób zdjęcie i współrzędne (x, y) w granicach obrazu oraz maksymalną długość krzywej. Wyprowadź ten sam obraz z dodaną czarną krzywą, która podąża za kątami odcienia, zaczynając od (x, y) i kończy się, gdy osiągnie maksymalną długość lub osiągnie granicę obrazu.
W szczególności rozpocznij krzywą od (x, y) i zmierz tam kąt barwy. Idź o jedną jednostkę (szerokość jednego piksela) w tym kierunku, zauważając, że twoja nowa pozycja najprawdopodobniej nie jest współrzędną całkowitą . Zaznacz kolejny punkt na krzywej i rusz się ponownie, używając odcienia z najbliższego piksela (używając czegoś w rodzaju floor
lub round
, nie będę tego dokładnie sprawdzać). Kontynuuj w ten sposób, aż krzywa wyjdzie poza granice lub przekroczy maksymalną długość. Aby zakończyć, wykreśl wszystkie punkty krzywej jako pojedyncze czarne piksele (ponownie użyj najbliższych pikseli) nałożone na obraz i wyślij ten nowy obraz.
„Kąt odcienia” to tylko odcień :
hue = atan2(sqrt(3) * (G - B), 2 * R - G - B)
Zauważ, że dla wartości w skali szarości, które technicznie nie mają odcienia, zwraca 0, ale to jest w porządku.
(Ta formuła wykorzystuje atan2
większość wbudowanych bibliotek matematycznych. R, G, B mają wartość od 0 do 1, a nie od 0 do 255.)
- Możesz użyć dowolnego popularnego formatu plików bezstratnych, a także dowolnych bibliotek obrazów.
- Weź dane wejściowe ze standardowego wiersza poleceń lub wiersza poleceń albo napisz funkcję z argumentami nazwy pliku obrazu, xiy oraz maksymalnej długości.
- Maksymalna długość i xiy są zawsze liczbami całkowitymi nieujemnymi. Możesz założyć, że xiy są w zakresie.
- Zapisz obraz wyjściowy z wybraną nazwą lub po prostu go wyświetl.
- Twoja implementacja nie musi dokładnie pasować do fragmentu. Kilka pikseli w nieco różnych miejscach ze względu na nieco inną metodę zaokrąglania / obliczania jest w porządku. (W chaotycznych przypadkach może to prowadzić do krzywych, które kończą się zasadniczo inaczej, ale dopóki wyglądają poprawnie wizualnie, jest w porządku).
Punktacja
Najmniejsze przesłanie w bajtach wygrywa.