テストタスク。 任意のポリゴン内のポイントのエントリを確認する





入門



この出版物に関心がある可能性のある人は、すぐに予約してください。 これらは、キャンバスを使用するブラウザでのベクターグラフィックスに関心のある初心者のDjango + jQueryプログラマです。 または、そのようなタスクを受け取った人々だけ。

それで、彼の地域の労働市場を絶えずスキャンしている間に、私は有名な地元企業のウェブ開発者として非常に興味深い仕事に出会いました。 職務明細書には、python + django開発者が必要であると書かれています。 履歴書を送信した後、次のようなテストタスクを受け取りました。



DjangoでWebアプリケーションを作成する必要があります。このアプリケーションは、任意の(凸ではない)多角形のポイントの発生の事実を決定します。 クライアントパーツは、ブラウザーで任意のポリゴンを(キャンバスまたはsvg、または一般に他の場所に)表示し、ユーザーが画面上のポイントを指定し、サーバーに要求を送信し、応答を受信して​​表示できるようにする必要があります。 サーバー部分は、それぞれ要求を受け入れ、ポイントが回線内にあるかどうかを判断し、クライアントに応答を返す必要があります。 Pythonのサーバー部分、クライアント-HTML + JavaScriptまたはCoffeeScript。


割り当てを完了し、テストサーバーで結果を公開するのに数時間を費やした後、潜在的な雇用主の側で完全に無視することになりました。 私は気分を害することはありません。何かが起こっても、タスクが面白くなればなるほど、その実装は多くの喜びをもたらしました。 善が消えなかったこと-私はそれをここに公開します。



行こう



まず、サイトを準備し、virtualenvを使用しました。



scherbin@scherbin-pc ~$ cd WebDev/venvs scherbin@scherbin-pc ~/WebDev/venvs/ $ virtualenv test scherbin@scherbin-pc ~/WebDev/venvs/ $ cd test scherbin@scherbin-pc ~/WebDev/venvs/test/ $ source bin/activate
      
      





必要なソフトウェアをインストールして、ここでプロジェクトを作成します。



 (test)scherbin@scherbin-pc ~/WebDev/venvs/test/ $ pip install django (test)scherbin@scherbin-pc ~/WebDev/venvs/test/ $ django-admin startproject mytest (test)scherbin@scherbin-pc ~/WebDev/venvs/test/ $ cd mytest
      
      





プロジェクトは、 startapiの 2つのアプリケーションで構成されます。 1つ目はユーザーのブラウザにHTMLとJavaScript、つまりフロントエンドを提供し、2つ目はフロントエンドへのAJAXリクエスト、つまりバックエンドを処理します。 それらを作成します。



 (test)scherbin@scherbin-pc ~/WebDev/venvs/test/mytest/ $ django-admin startapp start (test)scherbin@scherbin-pc ~/WebDev/venvs/test/mytest/ $ django-admin startapp api
      
      





構造



プロジェクトのバックボーンができたので、創造性に直接進むことができます。 まず、プロジェクト構造を書き留めます。 上記のように、フロントエンドとバックエンドの2つの部分で構成されます。



フロントエンド


キャンバスを使用してブラウザで任意のポリゴンを出力し、ユーザーがクリックしたことを処理します。 AJAXリクエストを介してバックエンドがクリックされると、2つのものがJSON形式で転送されます。



  1. ポリゴン座標の配列。
  2. ユーザーがクリックしたポイントの座標。


それに基づく回答を受け取った後、クリックポイントに直径5ピクセルの円が描画されます。 緑(ポリゴンに含まれる)または赤(含まれない)の色。



バックエンド


フロントエンドからリクエストを受け取り、ポイントがポリゴンに属していることを計算し、結果をポイント座標とエントリ属性のブール値の形式で返します。 ご覧のとおり、ポリゴンはサーバーに保存されておらず、ポリゴンが変更された場合にバックエンドが使用される可能性があります。



実装



まず、ユーザーのブラウザーにポリゴンを表示する必要があります。 メイン(ミニプロジェクトでは唯一の)HTMLページを作成します。



mytest / start / templates / start / index.html

 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title> </title> {% load staticfiles %} <script src="{% static 'js/jquery-1.12.0.min.js' %}"></script> <script src="{% static 'js/main.js' %}"></script> </head> <body> <style> canvas#canvas-main { border: 1px solid darkgray; } </style> <canvas id="canvas-main"></canvas> </body> </html>
      
      





ページのコードからわかるように、jQueryライブラリバージョン1.12.0が使用され、 main.jsファイルにはルーチン全体を実装するJavaScriptコードが含まれています。 つまり、ポリゴンの描画、クリックの処理、バックエンドとの通信。 実際、これはミニプロジェクトのメインファイルです。



mytest / start / static / js / main.js:

 $(function() { /** *    */ var polygon = [ [200, 50], [415, 80], [550, 200], [700, 200], [300, 400], [750, 580], [150, 530], [100, 150], [300, 250], [200, 50] ]; /** *   */ var canvasWidth = 800; var canvasHeight = 600; /** *           */ var drawPolygon = function(id, coords) { var canvas = $("#"+id); if (canvas.length) { var context = canvas[0].getContext("2d"); context.canvas.width = canvasWidth; context.canvas.height = canvasHeight; context.beginPath(); for (var i = 0; i < coords.length; i++) { if (i == 0) context.moveTo(coords[i][0], coords[i][1]); else context.lineTo(coords[i][0], coords[i][1]); } context.strokeStyle = '#0000'; context.stroke(); } }; /** *      */ $(document).on("click", "#canvas-main", function(event){ //    var x = event.pageX-$(this).offset().left; var y = event.pageY-$(this).offset().top; //    .           var query = { "polygon": polygon, "point": [x, y] }; //     var context = $(this)[0].getContext("2d"); //  POST    $.ajax({ type: "POST", url: '/api/in_polygon', data: JSON.stringify(query), success: function(data) { //    p = data['point']; //      context.beginPath(); context.arc(p[0], p[1], 5, 0, 2 * Math.PI, false); //          if (data['in_polygon']) context.fillStyle = "#73AD21"; else context.fillStyle = "#FF0000"; context.fill(); } }); }); /** *       */ drawPolygon("canvas-main", polygon); });
      
      





次に、ポリゴンへのポイントのエントリの検証を実装する必要があります。 使用されるアルゴリズムは、最も単純なレイトレーシングです。 ポリゴンのすべての面は、ユーザーがクリックしたポイントから来る光線との交差について順次チェックされます。 偶数の交差点または交差点がまったくない場合は、ポリゴンの外側のポイントです。 交差点の数は奇数です-内側の点。 次は、バックエンドAPIアプリケーションのpython実装です。



mytest / api / views.py:

 # -*- coding: utf-8 -*- import json from django.http import HttpResponse, JsonResponse # Create your views here. def in_polygon(request): if request.method == 'POST': data = json.loads(request.body) in_polygon = False # Main algorithms x = data['point'][0] y = data['point'][1] for i in range(len(data['polygon'])): xp = data['polygon'][i][0] yp = data['polygon'][i][1] xp_prev = data['polygon'][i-1][0] yp_prev = data['polygon'][i-1][1] if (((yp <= y and y < yp_prev) or (yp_prev <= y and y < yp)) and (x > (xp_prev - xp) * (y - yp) / (yp_prev - yp) + xp)): in_polygon = not in_polygon response = {u'in_polygon': in_polygon, u'point': [x, y]} return JsonResponse(response) else: return HttpResponse(u'    POST');
      
      





これで、主な機能の準備ができました。 この全体を機能させることは残っています。 これを行うには、3つのファイルを編集します。



mytest / mytest / settings.py

 # Application definition INSTALLED_APPS = [ ... 'start', 'api', ]
      
      







mytest / mytest / urls.py

 from django.conf.urls import * from django.contrib import admin from start.views import * urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api/', include('api.urls')), url(r'^$', start_index), ]
      
      







mytest / api / urls.py

 from django.conf.urls import * from api.views import * urlpatterns = [ url(r'^in_polygon$', in_polygon, name='in_polygon') ]
      
      





これから、Djangoに組み込まれたテストWebサーバーを実行できます。

 (test)scherbin@scherbin-pc ~/WebDev/venvs/test/mytest/ $ ./manage.py runserver
      
      





そして、 localhost :8000 /のブラウザーに移動して、緑と赤のドットを再生します。 投稿の冒頭にあるような写真が表示されるはずです。



All Articles