1
0
mirror of https://github.com/ToxicCrack/PrintABrick.git synced 2025-05-18 13:10:08 -07:00

Recursive load ldraw model subparts, Enable single model load

This commit is contained in:
David Hübner 2017-04-10 16:52:31 +02:00
parent 88c443b4ed
commit 36a4e0e73d
6 changed files with 184 additions and 147 deletions

View File

@ -14,13 +14,9 @@ services:
arguments: ['%rebrickable_url%'] arguments: ['%rebrickable_url%']
parent: service.loader parent: service.loader
util.dat.parser:
class: AppBundle\Utils\DatParser
arguments: ['@app.relation.mapper']
service.loader.ldraw: service.loader.ldraw:
class: AppBundle\Service\Loader\LDrawLoaderService class: AppBundle\Service\Loader\LDrawLoaderService
arguments: ['@oneup_flysystem.ldraw_library_filesystem','@service.ldview', '%ldraw_url%', '@manager.ldraw', '@util.dat.parser'] arguments: ['@oneup_flysystem.ldraw_library_filesystem','@service.ldview', '@manager.ldraw', '@app.relation.mapper']
parent: service.loader parent: service.loader
service.loader.relation: service.loader.relation:

View File

@ -1,39 +0,0 @@
<?php
namespace AppBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class LoadLDRawLibraryCommand extends ContainerAwareCommand
{
protected function configure()
{
$this
->setName('app:load:ldraw')
->setDescription('Loads LDraw library parts')
->setHelp('This command allows you to..')
->addArgument('file', InputArgument::OPTIONAL, 'Model to load');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$ldrawLoader = $this->getContainer()->get('service.loader.ldraw');
$ldrawLoader->setOutput($output);
//TODO log errors
try {
// TODO handle relative path to dir
if (($ldrawPath = $input->getArgument('file')) != null) {
$ldrawPath = $ldrawLoader->loadModel($ldrawPath);
} else {
$ldrawLoader->loadAllModels();
}
} catch (\Exception $e) {
printf($e->getMessage());
}
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace AppBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class LoadModelsCommand extends ContainerAwareCommand
{
protected function configure()
{
$this
->setName('app:load:models')
->setDescription('Loads LDraw library models into database')
->setHelp('This command allows you to load LDraw library models into while converting .dat files to .stl')
->setDefinition(
new InputDefinition(array(
new InputOption('images', 'i'),
new InputOption('ldraw', 'l', InputOption::VALUE_REQUIRED),
new InputOption('file', 'f', InputOption::VALUE_REQUIRED),
))
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$ldrawLoader = $this->getContainer()->get('service.loader.ldraw');
$ldrawLoader->setOutput($output);
//TODO log errors
try {
// TODO handle relative path to dir
if (($ldrawPath = $input->getOption('file')) != null) {
$ldrawLoader->loadFileContext($ldrawPath);
$model = $ldrawLoader->loadModel($ldrawPath);
if($model !== null) {
$this->getContainer()->get('manager.ldraw.model')->getRepository()->save($model);
}
} else {
$ldrawLoader->loadAllModels();
}
} catch (\Exception $e) {
printf($e->getMessage());
}
}
}

View File

@ -25,17 +25,17 @@ class SubpartManager extends BaseManager
* *
* @return Subpart * @return Subpart
*/ */
public function create($parent, $child) public function create($parent, $child, $count)
{ {
if (($subpart = $this->repository->findOneByKeys($parent, $child))) { // if (($subpart = $this->repository->findOneByKeys($parent, $child))) {
$subpart->setCount($subpart->getCount() + 1); // $subpart->setCount($count);
} else { // } else {
$subpart = new Subpart(); $subpart = new Subpart();
$subpart $subpart
->setParent($parent) ->setParent($parent)
->setSubpart($child) ->setSubpart($child)
->setCount(1); ->setCount($count);
} // }
return $subpart; return $subpart;
} }

View File

@ -2,19 +2,17 @@
namespace AppBundle\Service\Loader; namespace AppBundle\Service\Loader;
use AppBundle\Entity\LDraw\Category; use AppBundle\Entity\LDraw\Alias;
use AppBundle\Entity\LDraw\Model; use AppBundle\Entity\LDraw\Model;
use AppBundle\Entity\LDraw\Type; use AppBundle\Entity\LDraw\Type;
use AppBundle\Exception\FileNotFoundException;
use AppBundle\Manager\LDrawManager; use AppBundle\Manager\LDrawManager;
use AppBundle\Service\LDViewService; use AppBundle\Service\LDViewService;
use AppBundle\Utils\DatParser; use AppBundle\Utils\DatParser;
use AppBundle\Utils\RelationMapper;
use League\Flysystem\Adapter\Local; use League\Flysystem\Adapter\Local;
use League\Flysystem\File;
use League\Flysystem\Filesystem; use League\Flysystem\Filesystem;
//use Symfony\Component\Asset\Exception\LogicException; //use Symfony\Component\Asset\Exception\LogicException;
use Symfony\Component\Asset\Exception\LogicException;
use Symfony\Component\Console\Helper\ProgressBar;
//TODO refactor //TODO refactor
class LDrawLoaderService extends BaseLoaderService class LDrawLoaderService extends BaseLoaderService
@ -22,12 +20,12 @@ class LDrawLoaderService extends BaseLoaderService
/** /**
* @var Filesystem * @var Filesystem
*/ */
private $ldrawLibraryFilesystem; private $ldrawLibrary;
/** /**
* @var string download URL with current LDraw library * @var Filesystem
*/ */
private $ldraw_url; private $fileContext;
/** /**
* @var LDViewService * @var LDViewService
@ -40,36 +38,62 @@ class LDrawLoaderService extends BaseLoaderService
/** @var DatParser */ /** @var DatParser */
private $datParser; private $datParser;
private $newModels;
/** @var RelationMapper */
protected $relationMapper;
/** /**
* LDrawLoaderService constructor. * LDrawLoaderService constructor.
* @param Filesystem $ldrawLibraryFilesystem * @param Filesystem $ldrawLibraryFilesystem
* @param LDViewService $LDViewService * @param LDViewService $LDViewService
* @param $ldraw_url
* @param LDrawManager $ldrawService * @param LDrawManager $ldrawService
* @param DatParser $datParser * @param RelationMapper $relationMapper
*/ */
public function __construct($ldrawLibraryFilesystem, $LDViewService, $ldraw_url, $ldrawService, $datParser) public function __construct($ldrawLibraryFilesystem, $LDViewService, $ldrawService, $relationMapper)
{ {
$this->LDViewService = $LDViewService; $this->LDViewService = $LDViewService;
$this->ldraw_url = $ldraw_url;
$this->ldrawService = $ldrawService; $this->ldrawService = $ldrawService;
$this->datParser = $datParser; $this->datParser = new DatParser();
$this->ldrawLibraryFilesystem = $ldrawLibraryFilesystem; $this->ldrawLibrary = $ldrawLibraryFilesystem;
$this->relationMapper = $relationMapper;
}
private function dumpModel($model, $level = 1) {
$level = $level + 1;
dump(str_repeat("-", 2*$level).'> '.$model->getNumber());
foreach ($model->getSubparts() as $subpart) {
$this->dumpModel($subpart->getSubpart(), $level);
}
} }
public function loadAllModels() public function loadAllModels()
{ {
$files = $this->ldrawLibraryFilesystem->get('parts')->getContents(); $files = $this->ldrawLibrary->get('parts')->getContents();
$modelManager = $this->ldrawService->getModelManager(); $modelManager = $this->ldrawService->getModelManager();
$this->initProgressBar(count($files)); $this->initProgressBar(count($files));
foreach ($files as $file) { foreach ($files as $file) {
if ($file['type'] == 'file' && $file['extension'] == 'dat') { if ($file['type'] == 'file' && $file['extension'] == 'dat') {
$model = $this->loadModel($this->ldrawLibraryFilesystem->getAdapter()->getPathPrefix().$file['path']);
if($model) $this->newModels = [];
$model = $this->loadModel($this->ldrawLibrary->getAdapter()->getPathPrefix().$file['path']);
if($model !== null) {
// dump($model->getNumber());
try {
$modelManager->getRepository()->save($model); $modelManager->getRepository()->save($model);
} catch (\Exception $exception) {
dump($exception);
// dump($model);
$this->dumpModel($model);
exit();
}
}
} }
$this->progressBar->advance(); $this->progressBar->advance();
@ -86,26 +110,49 @@ class LDrawLoaderService extends BaseLoaderService
*/ */
public function loadModel($file) public function loadModel($file)
{ {
$model = null;
$modelManager = $this->ldrawService->getModelManager(); $modelManager = $this->ldrawService->getModelManager();
$subpartManager = $this->ldrawService->getSubpartManager(); $subpartManager = $this->ldrawService->getSubpartManager();
$aliasManager = $this->ldrawService->getAliasManager();
if($model = $modelManager->findByNumber(basename($file,'.dat'))) { if(($model = $modelManager->findByNumber(basename($file,'.dat'))) || ($model = isset($this->newModels[basename($file,'.dat')]) ? $this->newModels[basename($file,'.dat')] : null)) {
$this->LDViewService->datToPng($file);
return $model; return $model;
} }
try {
$header = $this->datParser->parse($file); $header = $this->datParser->parse($file);
} catch (\Exception $e) {
dump($e);
return null;
}
if ($this->isModelIncluded($header)) { if ($this->isModelIncluded($header)) {
if (isset($header['parent']) && ($parent = $this->getModelParent($header['parent'])) && ($parentFile = $this->findModelFile($parent))) {
if($this->relationMapper->find($header['id'], 'alias_model') !== $header['id']) {
$parentFile = $this->findModelFile($this->relationMapper->find($header['id'], 'alias_model'));
} else {
$parentFile = isset($header['parent']) && strpos($header['parent'], 's\\') === false ? $this->findModelFile($header['parent']) : null;
}
if ($parentFile) {
try {
$parentModel = $this->loadModel($parentFile); $parentModel = $this->loadModel($parentFile);
if ($parentModel) { if($parentModel) {
$alias = $aliasManager->create($header['id'], $parentModel); $alias = new Alias();
$aliasManager->getRepository()->save($alias); $alias->setNumber($header['id']);
$this->progressBar->advance(); $alias->setModel($parentModel);
} $parentModel->addAlias($alias);
$this->newModels[$parentModel->getNumber()] = $parentModel;
return $parentModel; return $parentModel;
}
} catch (\Exception $e) {
dump('b');
dump($e->getMessage());
return null;
}
} else { } else {
$model = $modelManager->create($header['id']); $model = $modelManager->create($header['id']);
$model->setName($header['name']); $model->setName($header['name']);
@ -119,19 +166,21 @@ class LDrawLoaderService extends BaseLoaderService
} }
if (isset($header['subparts'])) { if (isset($header['subparts'])) {
foreach ($header['subparts'] as $subpartId) { foreach ($header['subparts'] as $subpartId => $count) {
$subpartId = $this->getModelParent($subpartId); if(strpos($subpartId, 's\\') === false) {
if(($subpartFile = $this->findModelFile($subpartId)) != null) {
$subModel = $modelManager->getRepository()->findOneBy(['number'=>$subpartId]); try {
if(!$subModel && ($subpartFile = $this->findModelFile($subpartId)) != null) {
$subModel = $this->loadModel($subpartFile); $subModel = $this->loadModel($subpartFile);
}
if ($subModel) { if ($subModel) {
$subpart = $subpartManager->create($model, $subModel); $subpart = $subpartManager->create($model,$subModel,$count);
$subpartManager->getRepository()->save($subpart); $model->addSubpart($subpart);
$this->progressBar->advance(); }
} catch (\Exception $e) {
dump('c');
dump($e->getMessage());
}
}
} }
} }
} }
@ -140,10 +189,12 @@ class LDrawLoaderService extends BaseLoaderService
$model->setModified($header['modified']); $model->setModified($header['modified']);
$model->setPath($this->loadStlModel($file)); $model->setPath($this->loadStlModel($file));
$this->newModels[$model->getNumber()] = $model;
}
}
return $model; return $model;
} }
}
}
/** /**
* Find model file on ldraw filesystem. * Find model file on ldraw filesystem.
@ -154,40 +205,20 @@ class LDrawLoaderService extends BaseLoaderService
*/ */
private function findModelFile($id) private function findModelFile($id)
{ {
$path = 'parts/'.strtolower($id).'.dat'; $filename = strtolower($id).'.dat';
if ($this->ldrawLibraryFilesystem->has($path)) {
return $this->ldrawLibraryFilesystem->getAdapter()->getPathPrefix().$path; if($this->fileContext && $this->fileContext->has($filename)) {
return $this->fileContext->getAdapter()->getPathPrefix().$filename;
} else if ($this->ldrawLibrary->has('parts/'.$filename)) {
return $this->ldrawLibrary->getAdapter()->getPathPrefix().'parts/'.$filename;
} }
return null; return null;
} }
/** public function loadFileContext($file) {
* Recursively load model parent id of model with $number id. $adapter = new Local(dirname(realpath($file)));
* $this->fileContext = new Filesystem($adapter);
* @param string $number
*
* @return string
*/
private function getModelParent($number)
{
if (($file = $this->findModelFile($number)) == null) {
return $number;
}
$header = $this->datParser->parse($file);
do {
$parent = isset($header['parent']) ? $header['parent'] : null;
if ($file = $this->findModelFile($parent)) {
$header = $this->datParser->parse($file);
} else {
break;
}
} while ($parent);
return $header['id'];
} }
/** /**
@ -201,10 +232,9 @@ class LDrawLoaderService extends BaseLoaderService
{ {
// Do not include sticker parts and incomplete parts // Do not include sticker parts and incomplete parts
if ( if (
strpos($header['id'], 's') !== 0 $header['type'] != 'Subpart'
&& $header['type'] != 'Subpart'
&& $header['type'] != 'Sticker' && $header['type'] != 'Sticker'
&& !(($header['type'] == 'Printed') && $this->findModelFile($header['parent'])) // && !(($header['type'] == 'Printed') && $this->findModelFile($header['parent']))
) { ) {
return true; return true;
} }

View File

@ -8,19 +8,6 @@ use Symfony\Component\Asset\Exception\LogicException;
class DatParser class DatParser
{ {
/** @var RelationMapper */
protected $relationMapper;
/**
* DatParser constructor.
*
* @param RelationMapper $relationMapper
*/
public function __construct($relationMapper)
{
$this->relationMapper = $relationMapper;
}
/** /**
* Parse LDraw .dat file header identifying model store data to array. * Parse LDraw .dat file header identifying model store data to array.
* *
@ -93,18 +80,20 @@ class DatParser
} }
} }
} elseif (strpos($line, '1 ') === 0) { } elseif (strpos($line, '1 ') === 0) {
$header['subparts'][] = $this->getAlias($line); $id = $this->getAlias($line);
if(isset($header['subparts'][$id])) {
$header['subparts'][$id] = $header['subparts'][$id] + 1;
} else {
$header['subparts'][$id] = 1;
}
} }
} }
if ($this->isStickerShortcutPart($header['name'], $header['id'])) { if ($this->isStickerShortcutPart($header['name'], $header['id'])) {
$header['type'] = 'Sticker'; $header['type'] = 'Sticker';
} elseif (($parent = $this->relationMapper->find($header['id'], 'alias_model')) != $header['id']) {
$header['type'] = 'Alias';
$header['subparts'] = null;
$header['parent'] = $parent;
} elseif (isset($header['subparts']) && count($header['subparts']) == 1 && in_array($header['type'], ['Part Alias', 'Shortcut Physical_Colour', 'Shortcut Alias', 'Part Physical_Colour'])) { } elseif (isset($header['subparts']) && count($header['subparts']) == 1 && in_array($header['type'], ['Part Alias', 'Shortcut Physical_Colour', 'Shortcut Alias', 'Part Physical_Colour'])) {
$header['parent'] = $header['subparts'][0]; $header['parent'] = array_keys($header['subparts'])[0];
$header['subparts'] = null; $header['subparts'] = null;
} elseif ($parent = $this->getPrintedParentId($header['id'])) { } elseif ($parent = $this->getPrintedParentId($header['id'])) {
$header['type'] = 'Printed'; $header['type'] = 'Printed';
@ -118,19 +107,26 @@ class DatParser
$header['type'] = 'Obsolete/Subpart'; $header['type'] = 'Obsolete/Subpart';
} }
$header['name'] = ltrim($header['name'], '~'); if(!isset($header['type'])) {
$header['type'] = 'Unknown';
}
if(!isset($header['modified'])) {
$header['modified'] = null;
}
// $header['name'] = ltrim($header['name'], '~');
fclose($handle); fclose($handle);
return $header; return $header;
} }
} catch (\Exception $exception) { } catch (\Exception $exception) {
dump($exception->getMessage()); dump($exception);
throw new LogicException('Error parsing '.$file);
return null;
} }
} }
return null; throw new LogicException('File not found '.$file);
} }
/** /**
@ -147,6 +143,8 @@ class DatParser
*/ */
public function getAlias($line) public function getAlias($line)
{ {
if(preg_match('/^1 16 0 0 0 -1 0 0 0 1 0 0 0 1 (.*)\.(dat|DAT)$/', $line, $matches))
return null;
if (preg_match('/^1(.*) (.*)\.(dat|DAT)$/', $line, $matches)) { if (preg_match('/^1(.*) (.*)\.(dat|DAT)$/', $line, $matches)) {
return $matches[2]; return $matches[2];
} }