import os.path import struct import re from hashlib import md5 from datetime import datetime, timedelta from django.urls import reverse from django.contrib.auth.models import User from django.db import models vertex_pattern = re.compile(r'vertex\s+([0-9.e+-]+)\s+([0-9.e+-]+)\s+([0-9.e+-]+)') 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)) 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)) class Geometry(models.Model): 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) 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("