From e2b407678ce04401357512e365e127a4acf476b7 Mon Sep 17 00:00:00 2001 From: Kseninia Mikhaylova Date: Mon, 20 May 2024 15:21:02 +0300 Subject: [PATCH] load image from server --- .vscode/PythonImportHelper-v2-Completion.json | 105 +++++++- admin_front/assets/css/main.css | 3 + admin_front/helpers.ts | 4 +- admin_front/pages/plan/index.vue | 231 ++++++++++++------ back/api/models.py | 26 +- back/api/serializers.py | 27 +- back/api/tracer.py | 2 +- back/api/views.py | 39 ++- back/back/urls.py | 3 +- front/src/components/Floorplan.vue | 28 ++- front/src/stores/floorplan.ts | 4 +- 11 files changed, 353 insertions(+), 119 deletions(-) diff --git a/.vscode/PythonImportHelper-v2-Completion.json b/.vscode/PythonImportHelper-v2-Completion.json index 67959f6..cd9af35 100644 --- a/.vscode/PythonImportHelper-v2-Completion.json +++ b/.vscode/PythonImportHelper-v2-Completion.json @@ -1533,6 +1533,54 @@ "detail": "django.db", "documentation": {} }, + { + "label": "migrations", + "importPath": "django.db", + "description": "django.db", + "isExtraImport": true, + "detail": "django.db", + "documentation": {} + }, + { + "label": "models", + "importPath": "django.db", + "description": "django.db", + "isExtraImport": true, + "detail": "django.db", + "documentation": {} + }, + { + "label": "migrations", + "importPath": "django.db", + "description": "django.db", + "isExtraImport": true, + "detail": "django.db", + "documentation": {} + }, + { + "label": "models", + "importPath": "django.db", + "description": "django.db", + "isExtraImport": true, + "detail": "django.db", + "documentation": {} + }, + { + "label": "migrations", + "importPath": "django.db", + "description": "django.db", + "isExtraImport": true, + "detail": "django.db", + "documentation": {} + }, + { + "label": "models", + "importPath": "django.db", + "description": "django.db", + "isExtraImport": true, + "detail": "django.db", + "documentation": {} + }, { "label": "models", "importPath": "django.db", @@ -8242,6 +8290,33 @@ "detail": "back.api.migrations.0001_initial", "documentation": {} }, + { + "label": "Migration", + "kind": 6, + "importPath": "back.api.migrations.0002_floorplan_d_border_floorplan_d_size_floorplan_paths", + "description": "back.api.migrations.0002_floorplan_d_border_floorplan_d_size_floorplan_paths", + "peekOfCode": "class Migration(migrations.Migration):\n dependencies = [\n ('api', '0001_initial'),\n ]\n operations = [\n migrations.AddField(\n model_name='floorplan',\n name='d_border',\n field=models.IntegerField(default=1),\n preserve_default=False,", + "detail": "back.api.migrations.0002_floorplan_d_border_floorplan_d_size_floorplan_paths", + "documentation": {} + }, + { + "label": "Migration", + "kind": 6, + "importPath": "back.api.migrations.0003_alter_floorplan_paths", + "description": "back.api.migrations.0003_alter_floorplan_paths", + "peekOfCode": "class Migration(migrations.Migration):\n dependencies = [\n ('api', '0002_floorplan_d_border_floorplan_d_size_floorplan_paths'),\n ]\n operations = [\n migrations.AlterField(\n model_name='floorplan',\n name='paths',\n field=models.TextField(),\n ),", + "detail": "back.api.migrations.0003_alter_floorplan_paths", + "documentation": {} + }, + { + "label": "Migration", + "kind": 6, + "importPath": "back.api.migrations.0004_alter_floorplan_d_border_alter_floorplan_d_size", + "description": "back.api.migrations.0004_alter_floorplan_d_border_alter_floorplan_d_size", + "peekOfCode": "class Migration(migrations.Migration):\n dependencies = [\n ('api', '0003_alter_floorplan_paths'),\n ]\n operations = [\n migrations.AlterField(\n model_name='floorplan',\n name='d_border',\n field=models.IntegerField(blank=True, null=True),\n ),", + "detail": "back.api.migrations.0004_alter_floorplan_d_border_alter_floorplan_d_size", + "documentation": {} + }, { "label": "ApiConfig", "kind": 6, @@ -8256,7 +8331,7 @@ "kind": 6, "importPath": "back.api.models", "description": "back.api.models", - "peekOfCode": "class Product(models.Model):\n title = models.CharField(max_length=100)\n description = models.TextField(default=None, null=True)\n model3d = models.FileField(\n default=None, blank=True, null=True, upload_to=\"files\"\n )\n image1 = models.ImageField(\n default=None, blank=True, null=True, upload_to=\"files\"\n )\n image2 = models.ImageField(", + "peekOfCode": "class Product(models.Model):\n title = models.CharField(max_length=100)\n description = models.TextField(default=None, null=True)\n model3d = models.FileField(default=None, blank=True, null=True, upload_to=\"files\")\n image1 = models.ImageField(default=None, blank=True, null=True, upload_to=\"files\")\n image2 = models.ImageField(default=None, blank=True, null=True, upload_to=\"files\")\n image3 = models.ImageField(default=None, blank=True, null=True, upload_to=\"files\")\n def __str__(self):\n return self.title\nclass Floorplan(models.Model):", "detail": "back.api.models", "documentation": {} }, @@ -8265,7 +8340,7 @@ "kind": 6, "importPath": "back.api.models", "description": "back.api.models", - "peekOfCode": "class Floorplan(models.Model):\n title = models.CharField(max_length=200)\n np_field = models.TextField()", + "peekOfCode": "class Floorplan(models.Model):\n title = models.CharField(max_length=200)\n np_field = models.TextField()\n d_size = models.IntegerField(null=True, blank=True)\n d_border = models.IntegerField(null=True, blank=True)\n paths = models.TextField()", "detail": "back.api.models", "documentation": {} }, @@ -8283,7 +8358,25 @@ "kind": 6, "importPath": "back.api.serializers", "description": "back.api.serializers", - "peekOfCode": "class FloorplanSerializer(serializers.Serializer):\n title = serializers.CharField(max_length=200)\n np_field = serializers.CharField()\n def create(self,validated_data):\n return Floorplan.objects.create(**validated_data)", + "peekOfCode": "class FloorplanSerializer(serializers.ModelSerializer):\n class Meta:\n model = Floorplan\n fields = [\n \"id\",\n \"title\",\n \"np_field\",\n \"d_border\",\n \"d_size\",\n \"paths\"", + "detail": "back.api.serializers", + "documentation": {} + }, + { + "label": "FloorplanListSerializer", + "kind": 6, + "importPath": "back.api.serializers", + "description": "back.api.serializers", + "peekOfCode": "class FloorplanListSerializer(serializers.ModelSerializer):\n class Meta:\n model = Floorplan\n fields = [\n \"id\",\n \"title\",\n ]", + "detail": "back.api.serializers", + "documentation": {} + }, + { + "label": "logger", + "kind": 5, + "importPath": "back.api.serializers", + "description": "back.api.serializers", + "peekOfCode": "logger = logging.getLogger(\"root\")\nclass ProductSerializer(serializers.HyperlinkedModelSerializer):\n class Meta:\n model = Product\n fields = [\n \"id\",\n \"title\",\n \"description\",\n \"model3d\",\n \"image1\",", "detail": "back.api.serializers", "documentation": {} }, @@ -8319,7 +8412,7 @@ "kind": 2, "importPath": "back.api.tracer", "description": "back.api.tracer", - "peekOfCode": "def parse_image(img):\n (img_h, img_w) = img.shape[:2]\n t = 1200\n w = t\n h = int((img_h / img_w) * t)\n img = cv2.resize(img, (w, h))\n gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n gray = 255 - gray\n gray = cv2.threshold(gray, 250, 255, cv2.THRESH_BINARY)[1]\n gray = cv2.blur(gray, (10, 5))", + "peekOfCode": "def parse_image(img):\n (img_h, img_w) = img.shape[:2]\n t = 1920\n w = t\n h = int((img_h / img_w) * t)\n img = cv2.resize(img, (w, h))\n gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n gray = 255 - gray\n gray = cv2.threshold(gray, 250, 255, cv2.THRESH_BINARY)[1]\n gray = cv2.blur(gray, (10, 5))", "detail": "back.api.tracer", "documentation": {} }, @@ -8337,7 +8430,7 @@ "kind": 6, "importPath": "back.api.views", "description": "back.api.views", - "peekOfCode": "class FloorplanView(APIView):\n parser_classes = (MultiPartParser,)\n def post(self, request):\n try:\n file = request.FILES[\"demo\"]\n logger.info(file.__dict__)\n res = parse_image(read_image(file.read()))\n serializer = FloorplanSerializer(\n data={\"title\": file.name, \"np_field\": res[\"b64\"].decode()}\n )", + "peekOfCode": "class FloorplanView(APIView):\n parser_classes = (MultiPartParser,)\n def post(self, request):\n try:\n file = request.FILES[\"demo\"]\n logger.info(file.__dict__)\n res = parse_image(read_image(file.read()))\n serializer = FloorplanSerializer(\n data={\n \"title\": file.name,", "detail": "back.api.views", "documentation": {} }, @@ -8553,7 +8646,7 @@ "kind": 5, "importPath": "back.back.urls", "description": "back.back.urls", - "peekOfCode": "urlpatterns = [\n path(\"admin/\", admin.site.urls),\n path(\"api/products\", csrf_exempt(views.Products.as_view())),\n path(\"api/floorplan\", csrf_exempt(views.FloorplanView.as_view())),\n] + static('/files', document_root='files')", + "peekOfCode": "urlpatterns = [\n path(\"admin/\", admin.site.urls),\n path(\"api/products\", csrf_exempt(views.Products.as_view())),\n path(\"api/floorplan/\", csrf_exempt(views.FloorplanView.as_view())),\n path(\"api/floorplan/\", csrf_exempt(views.FloorplanView.as_view())),\n] + static('/files', document_root='files')", "detail": "back.back.urls", "documentation": {} }, diff --git a/admin_front/assets/css/main.css b/admin_front/assets/css/main.css index 45f7b50..afbec47 100644 --- a/admin_front/assets/css/main.css +++ b/admin_front/assets/css/main.css @@ -33,3 +33,6 @@ @apply bg-surface-100 dark:bg-[rgba(255,255,255,0.03)] } +[data-pc-section="list"] { + @apply bg-slate-50 +} \ No newline at end of file diff --git a/admin_front/helpers.ts b/admin_front/helpers.ts index df0099a..a3cad98 100644 --- a/admin_front/helpers.ts +++ b/admin_front/helpers.ts @@ -1,5 +1,5 @@ -export function* chunks(arr: any, n: number) { +export function* chunks(arr: T[], n: number): Generator { for (let i = 0; i < arr.length; i += n) { yield arr.slice(i, i + n); } -} +} \ No newline at end of file diff --git a/admin_front/pages/plan/index.vue b/admin_front/pages/plan/index.vue index 81876b8..480bd28 100644 --- a/admin_front/pages/plan/index.vue +++ b/admin_front/pages/plan/index.vue @@ -1,16 +1,11 @@ \ No newline at end of file + + + \ No newline at end of file diff --git a/back/api/models.py b/back/api/models.py index a9a1dde..cb2edb7 100644 --- a/back/api/models.py +++ b/back/api/models.py @@ -1,27 +1,23 @@ from django.db import models +import json # Create your models here. class Product(models.Model): title = models.CharField(max_length=100) description = models.TextField(default=None, null=True) - model3d = models.FileField( - default=None, blank=True, null=True, upload_to="files" - ) - image1 = models.ImageField( - default=None, blank=True, null=True, upload_to="files" - ) - image2 = models.ImageField( - default=None, blank=True, null=True, upload_to="files" - ) - image3 = models.ImageField( - default=None, blank=True, null=True, upload_to="files" - ) + model3d = models.FileField(default=None, blank=True, null=True, upload_to="files") + image1 = models.ImageField(default=None, blank=True, null=True, upload_to="files") + image2 = models.ImageField(default=None, blank=True, null=True, upload_to="files") + image3 = models.ImageField(default=None, blank=True, null=True, upload_to="files") def __str__(self): return self.title - - + + class Floorplan(models.Model): title = models.CharField(max_length=200) - np_field = models.TextField() \ No newline at end of file + np_field = models.TextField() + d_size = models.IntegerField(null=True, blank=True) + d_border = models.IntegerField(null=True, blank=True) + paths = models.TextField() \ No newline at end of file diff --git a/back/api/serializers.py b/back/api/serializers.py index 4fa38ab..c8f5c17 100644 --- a/back/api/serializers.py +++ b/back/api/serializers.py @@ -1,6 +1,8 @@ from rest_framework import routers, serializers, viewsets from .models import Product, Floorplan +import logging +logger = logging.getLogger("root") class ProductSerializer(serializers.HyperlinkedModelSerializer): class Meta: @@ -16,9 +18,22 @@ class ProductSerializer(serializers.HyperlinkedModelSerializer): ] -class FloorplanSerializer(serializers.Serializer): - title = serializers.CharField(max_length=200) - np_field = serializers.CharField() - - def create(self,validated_data): - return Floorplan.objects.create(**validated_data) +class FloorplanSerializer(serializers.ModelSerializer): + class Meta: + model = Floorplan + fields = [ + "id", + "title", + "np_field", + "d_border", + "d_size", + "paths" + ] + +class FloorplanListSerializer(serializers.ModelSerializer): + class Meta: + model = Floorplan + fields = [ + "id", + "title", + ] \ No newline at end of file diff --git a/back/api/tracer.py b/back/api/tracer.py index 872f8de..f361a2e 100644 --- a/back/api/tracer.py +++ b/back/api/tracer.py @@ -31,7 +31,7 @@ def read_image(content: bytes) -> np.ndarray: def parse_image(img): (img_h, img_w) = img.shape[:2] - t = 1200 + t = 1920 w = t h = int((img_h / img_w) * t) img = cv2.resize(img, (w, h)) diff --git a/back/api/views.py b/back/api/views.py index f5fc7a3..e228b02 100644 --- a/back/api/views.py +++ b/back/api/views.py @@ -1,10 +1,10 @@ - +import json from rest_framework.parsers import JSONParser, MultiPartParser from rest_framework.views import APIView from django.http import JsonResponse from api.tracer import parse_image, read_image, numpy_zip_str_to_arr -from .serializers import FloorplanSerializer, ProductSerializer +from .serializers import FloorplanSerializer, FloorplanListSerializer, ProductSerializer from .models import Floorplan, Product import logging @@ -38,26 +38,43 @@ class FloorplanView(APIView): logger.info(file.__dict__) res = parse_image(read_image(file.read())) serializer = FloorplanSerializer( - data={"title": file.name, "np_field": res["b64"].decode()} + data={ + "title": file.name, + "np_field": res["b64"].decode(), + "paths": json.dumps(res["paths"]), + } ) - logger.info(res["b64"]) + if serializer.is_valid(): serializer.save() return JsonResponse( - data={"response": {"array": res["array"]}}, status=201 + data={ + "response": { + "np_field": res["array"], + "paths": res["paths"], + } + }, + status=201, ) + else: + logger.info(serializer.errors) return JsonResponse(serializer.errors, status=500) except Exception as e: logger.error(e) raise e - def get(self, request): + def get(self, request, id=None): try: - item = Floorplan.objects.last() - serializer = FloorplanSerializer(item, many=False) - data = serializer.data - data["np_field"] = numpy_zip_str_to_arr(data["np_field"]) - return JsonResponse(data, safe=False) + if id is not None: + item = Floorplan.objects.get(id=id) + serializer = FloorplanSerializer(item, many=False) + data = serializer.data + data["np_field"] = numpy_zip_str_to_arr(data["np_field"]) + return JsonResponse(data, safe=False) + else: + items = Floorplan.objects.only("id", "title").all() + serializer = FloorplanListSerializer(items, many=True) + return JsonResponse(serializer.data, safe=False) except Exception as e: logger.error(e) raise e diff --git a/back/back/urls.py b/back/back/urls.py index ecf0181..834f599 100644 --- a/back/back/urls.py +++ b/back/back/urls.py @@ -23,5 +23,6 @@ from django.views.decorators.csrf import csrf_exempt urlpatterns = [ path("admin/", admin.site.urls), path("api/products", csrf_exempt(views.Products.as_view())), - path("api/floorplan", csrf_exempt(views.FloorplanView.as_view())), + path("api/floorplan/", csrf_exempt(views.FloorplanView.as_view())), + path("api/floorplan/", csrf_exempt(views.FloorplanView.as_view())), ] + static('/files', document_root='files') diff --git a/front/src/components/Floorplan.vue b/front/src/components/Floorplan.vue index 4dd6b0f..8dc8bb7 100644 --- a/front/src/components/Floorplan.vue +++ b/front/src/components/Floorplan.vue @@ -12,7 +12,7 @@ const canvasElement = ref(); const context = ref(); const grid = ref() -const startPoint = ref<{ x: number, y: number }>({ x: 27, y: 38 }) +const startPoint = ref<{ x: number, y: number }>({ x: 25, y: 40 }) const endPoint = ref<{ x: number, y: number }>() const startToEndPath = ref() @@ -30,12 +30,26 @@ const newDraw = () => { lines.forEach((line, indexY) => { line.forEach((point, indexX) => { if (canvasElement.value && context.value) { - context.value.fillStyle = point > 0 ? 'red' : 'WHITE' + context.value.fillStyle = point > 0 ? 'purple' : 'WHITE' context.value.fillRect(indexX, indexY, 1, 1) } }) }); + // if (canvasElement.value && context.value) { + // context.value.clearRect(0, 0, canvasElement.value.width, canvasElement.value.height); + // if (!plan.value.hasOwnProperty('paths')) return + // (plan.value).paths.forEach((path: string) => { + // if (!context.value) return + // context.value.fillStyle = 'rgba(255, 0, 255, 0.25)' + // context.value.fill(new Path2D(path)); + + // context.value.strokeStyle = 'blue' + // context.value.stroke(new Path2D(path)); + // }); + // } + + const quantum_lines = plan.prepared_array quantum_lines.forEach((line, indexY) => { line.forEach((point, indexX) => { @@ -55,7 +69,7 @@ const newDraw = () => { const findPath = async () => { if (!endPoint.value) return - const localPath = finder.findPath( + const localPath = finder.findPath( Math.round(startPoint.value.x), Math.round(startPoint.value.y), Math.round(endPoint.value.x), @@ -75,11 +89,13 @@ onMounted(async () => { await floorplan.getData() newDraw() }) +const cw = 1920 +const ch = 800