past3d/pastebin/models.py

172 lines
5.3 KiB
Python
Raw Permalink Normal View History

2013-10-01 16:38:42 +02:00
import os.path
import struct
2013-10-10 17:46:22 +02:00
import re
2013-10-01 16:38:42 +02:00
from hashlib import md5
from datetime import datetime, timedelta
2013-10-01 16:38:42 +02:00
2023-07-12 19:44:08 +02:00
from django.urls import reverse
from django.contrib.auth.models import User
2013-10-01 16:38:42 +02:00
from django.db import models
2013-10-10 17:46:22 +02:00
vertex_pattern = re.compile(r'vertex\s+([0-9.e+-]+)\s+([0-9.e+-]+)\s+([0-9.e+-]+)')
2013-10-01 16:38:42 +02:00
2015-11-08 18:46:23 +01:00
2013-10-01 16:38:42 +02:00
def model_path(instance, filename):
ext = os.path.splitext(filename)[1]
md5sum = md5()
md5sum.update(instance.name.encode('utf-8') +
str(datetime.now()).encode('utf-8') +
filename.encode('utf-8'))
randomname = md5sum.hexdigest()
return os.path.join('models', '%s%s' % (randomname, ext))
2013-10-01 16:38:42 +02:00
def source_path(instance, filename):
ext = os.path.splitext(filename)[1]
md5sum = md5()
md5sum.update(instance.name.encode('utf-8') +
str(datetime.now()).encode('utf-8') +
filename.encode('utf-8'))
randomname = md5sum.hexdigest()
return os.path.join('sources', '%s%s' % (randomname, ext))
2013-10-01 16:38:42 +02:00
class Geometry(models.Model):
2023-07-12 19:44:08 +02:00
HOUR = 0
DAY = 1
WEEK = 2
MONTH = 3
FORERVER = 4
EXPIRATION_CHOICES = ((HOUR, 'one hour'), (DAY, 'one day'), (WEEK, 'one week'),
(MONTH, 'one month'), (FORERVER, 'forever'))
DELTAS = {
HOUR: timedelta(hours=1),
DAY: timedelta(days=1),
WEEK: timedelta(weeks=1),
MONTH: timedelta(weeks=4)
}
name = models.CharField(max_length=128)
description = models.TextField(blank=True)
user = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True)
expiration = models.IntegerField(default=0, choices=EXPIRATION_CHOICES)
public = models.BooleanField(default=True)
polycount = models.IntegerField(blank=True, default=0)
width = models.FloatField(blank=True, default=0)
depth = models.FloatField(blank=True, default=0)
height = models.FloatField(blank=True, default=0)
file = models.FileField(upload_to=model_path)
sourcefile = models.FileField(upload_to=source_path, blank=True)
2023-07-12 19:44:08 +02:00
def get_absolute_url(self):
return reverse('geometry_details', kwargs={'id': self.pk})
@classmethod
def get_latest(cls):
return cls.objects.all().filter(public=True).order_by('-date')[:10]
def get_expiration_date(self):
for expiration in [self.HOUR, self.DAY, self.WEEK, self.MONTH]:
if self.expiration == expiration:
return self.date + self.DELTAS[expiration]
return None
def _generate_meta_infos(self):
print("Generating metainfos %s" % self.name)
self.file.open()
count = 0
min_coord = [None, None, None]
max_coord = [None, None, None]
if self.file.read(5) != "solid":
print("binary")
# Skip header
self.file.seek(80)
count = struct.unpack("i", self.file.read(4))[0]
done = False
for pos in range(0, count):
# Skip normal (3 * 32bit)
self.file.seek(self.file.tell() + 3 * 4)
# Loop over each coordinate
for vert in range(0, 3):
# Loop over each coordinate
for i in range(0, 3):
x = struct.unpack("<f", self.file.read(4))[0]
if min_coord[i] is not None:
min_coord[i] = min(min_coord[i], x)
else:
min_coord[i] = x
if max_coord[i] is not None:
max_coord[i] = max(max_coord[i], x)
else:
max_coord[i] = x
# Skip attributes (16bit)
self.file.seek(self.file.tell() + 2)
else:
print("ascii")
line = self.file.readline()
while line != "":
line = line.strip()
if line.startswith("facet"):
count = count + 1
if line.startswith("vertex"):
coords = vertex_pattern.match(line).groups()
for i in range(0, 3):
x = float(coords[i])
if min_coord[i] is not None:
min_coord[i] = min(min_coord[i], x)
else:
min_coord[i] = x
if max_coord[i] is not None:
max_coord[i] = max(max_coord[i], x)
else:
max_coord[i] = x
line = self.file.readline()
self.file.close()
self.width = max_coord[0] - min_coord[0]
self.depth = max_coord[1] - min_coord[1]
self.height = max_coord[2] - min_coord[2]
self.polycount = count
self.save()
def get_polycount(self):
if self.polycount == 0:
self._generate_meta_infos()
return self.polycount
def get_width(self):
if self.polycount == 0:
self._generate_meta_infos()
return self.width
def get_depth(self):
if self.polycount == 0:
self._generate_meta_infos()
return self.depth
def get_height(self):
if self.polycount == 0:
self._generate_meta_infos()
return self.height