Système de simulation de script ZenCad 3D

Le travail que je veux porter à votre attention est une tentative d'écrire à nouveau un système de modélisation 3D scripté. Écrivez comme je voudrais la voir.


La recette du système ZenCad est assez simple. Le concept de script de modélisation 3D d'OpenScad, le noyau géométrique d'OpenCascade, python3 comme colle, la bibliothèque de calcul paresseux evalcache pour une mise en cache agressive des calculs. Ajouter les épices de quelques autres instruments, assaisonner le gui avec la sauce PyQt et servir, en remuant, sans secouer.


machine.png


Systèmes de CAO de script


CAD, ou selon notre CAD, est un système de conception assistée par ordinateur. Contrairement aux éditeurs 3D interactifs, les systèmes de CAO scriptés interprètent le mot "automatisé" dans le sens où ses créateurs le comprennent habituellement. C'est-à-dire, non pas comme un ensemble d'outils informatiques, mais comme un algorithme limpide qui ne nécessite une intervention humaine qu'au moment de sa création.


En travaillant en CAD scripté, nous ne dessinons pas le modèle directement sur l'écran, mais construisons le programme selon lequel le modèle est généré. Pour les personnes qui ne connaissent que la CAO interactive, cette approche peut être décrite comme une modélisation paramétrique absolue. À proprement parler, les scripts sont souvent utilisés pour compléter un environnement interactif, pour écrire des outils supplémentaires, mais travailler dans un CAD scripté d'une netteté paradigmatique nécessite une organisation différente du flux de travail, une façon de penser et est conçu pour une gamme légèrement différente de tâches.


Le CAD de script le plus célèbre et le plus pur à l'heure actuelle est OpenScad.


Au début était OpenScad


Il y a un certain cercle de personnes qui préfèrent la boussole pratique, SolidWorks, FreeCad, l'OpenScad banal et sans prétention. Il est assez difficile de répondre à la question de savoir quel est le secret de son succès, mais on peut affirmer avec certitude qu'il est léger, suffisamment flexible à utiliser et dispose d'un minimum de réglages. Certaines parties des modèles écrits dessus sont faciles à réutiliser.


Cependant, openscad a quelques défauts gênants:


  • openscad ne fonctionne qu'avec les réseaux maillés.
  • openscad a une limite d'évolutivité assez faible, il commence à accuser un retard important sur les grands modèles.
  • openscad est assez difficile à intégrer avec d'autres systèmes, c'est pourquoi utiliser son propre langage.

Malheureusement, malgré toute la puissance de l'approche de script, aller au-delà de la portée du clignotement utilitaire pour écrire des modèles simples avec OpenScad est assez problématique.


Langue et tout-tout


La première chose que je veux corriger ici est de prendre un langage à usage général comme outil de combat. L'utilisation d'un langage polyvalent vous permet d'utiliser l'intégralité de ses capacités syntaxiques et la combinaison de bibliothèques précédemment écrites pour résoudre des problèmes de modélisation 3D.


Comparaison des interfaces graphiques ZenCad et OpenScad

Interface ZenCad:
zencad.png


Interface OpenScad:
openscad.png


L'utilisation de python simplifie le code openscad en rendant le code du modèle plus transparent par rapport à OpenScad.


Exemple: CSG
#!/usr/bin/env python #coding: utf-8 from zencad import * lazy.diag = True c1 = 100 c2 = 130 c3 = c2/2 + 20 base = box(c1,c1,c1,center=True) f1 = ngon(r = 35, n = 3) f2 = ngon(r = 35, n = 5) f3 = circle(35) s1 = linear_extrude(f1, c2, center=True) s2 = linear_extrude(f2, c2, center=True).rotateY(deg(90)) s3 = linear_extrude(f3, c2, center=True).rotateX(deg(90)) #          3 . m1 = base - s1 - s2 - s3 m2 = base ^ s1 ^ s2 ^ s3 m3 = s1 + s2 + s3 ystep = 240 xstep = 240 fontpath = os.path.join(zencad.moduledir, "examples/fonts/testfont.ttf") #    .      . t1 = textshape("difference", fontpath, 40) t1c = t1.center() t1=t1.translate(-t1c.x, -t1c.y, 0).rotateZ(deg(45)) t2 = textshape("intersect", fontpath, 40) t2c = t2.center() t2=t2.translate(-t2c.x, -t2c.y, 0).rotateZ(deg(45)) t3 = textshape("union", fontpath, 40) t3c = t3.center() t3=t3.translate(-t3c.x, -t3c.y, 0).rotateZ(deg(45)) #  ,  . disp(base.forw(ystep)) disp(s1) disp(s2.left(xstep)) disp(s3.right(xstep)) disp(m1.back(ystep)) disp(m2.left(xstep).back(ystep)) disp(m3.right(xstep).back(ystep)) disp(t1.back(ystep).up(c3), Color(1,1,0)) disp(t2.left(xstep).back(ystep).up(c3), Color(1,1,0)) disp(t3.right(xstep).back(ystep).up(c3), Color(1,1,0)) disp(s1.left(xstep).back(ystep), Color(0.5,0,0,0.95)) disp(s2.left(xstep).back(ystep), Color(0.5,0,0,0.95)) disp(s3.left(xstep).back(ystep), Color(0.5,0,0,0.95)) disp(s1.back(ystep), Color(0.5,0,0,0.95)) disp(s2.back(ystep), Color(0.5,0,0,0.95)) disp(s3.back(ystep), Color(0.5,0,0,0.95)) show() 

boolean.png


Il est très pratique, par exemple, de filtrer un nuage de points en utilisant la syntaxe des générateurs.


Exemple: filtrage d'un tableau de points.
 #!/usr/bin/env python3 from zencad import * #  . ng = ngon(r = 10, n = 6) #      . vertices = ng.vertices() filtered_vertices = [v for v in vertices if vx < 0] #      . m = ng.fillet(4, filtered_vertices) disp(m) show() 

ngon


Grâce à python, occupant officieusement le titre de roi de la colle dans l'écosystème logiciel moderne, zencad s'intègre facilement avec d'autres bibliothèques et systèmes logiciels. Nous pouvons utiliser sympy dans un script pour générer une surface analytique, numpy pour traiter un nuage de points généré sur cette surface et, bien sûr, zencad pour la construction, la visualisation et le post-traitement.


Exemple: construction de surface simple point par point
 from zencad import * import numpy xcoords = numpy.linspace(-10,10,50) ycoords = numpy.linspace(-10,15,50) lines = [ interpolate([point(x, y, 0.01*(x**2 + y**3)) for x in xcoords]) for y in ycoords ] wires = [] for l in lines: trans = translate(0,0,-30) sf = l.endpoints() w=sew([l, segment(sf[0], trans(sf[0])), trans(l), segment(sf[1], trans(sf[1]))]) wires.append(w) for l in lines: disp(l.left(30)) disp(loft(wires) - halfspace().down(10)) show() 

chair.png


La base solide d'OpenCascade


Les mathématiques des maillages polygonaux sont beaucoup plus simples que les mathématiques de la représentation des limites, mais la représentation des limites est beaucoup plus pratique. En particulier, les maillages polygonaux ont un problème d'explosion combinatoire, qui se manifeste surtout quand vient le temps de rendre un modèle. Dans OpenScad, il est souvent nécessaire de développer un produit avec une résolution bien inférieure à la résolution d'un modèle réel, ce qui viole la pureté du paradigme.


Ainsi, le deuxième point de mise en œuvre est l'utilisation d'un noyau géométrique à part entière qui utilise la représentation des limites au lieu du modèle de maillage. Construit autour du noyau géométrique pirate d'OpenCascade, ZenCad, bien sûr, n'a pas pour objectif de fournir la totalité de ses capacités dans l'environnement python. Essayer de transmettre pleinement OpenCascade entraînerait l'écriture d'un deuxième pythonOCC. ZenCad prend le dessus, essayant de maintenir un équilibre entre fonctionnalité et ergonomie.


Exemple: bouteille de logiciel OpenCascade jouée dans ZenCad
 #!/usr/bin/env python3 #coding: utf-8 from zencad import * import zencad.surface as surface import zencad.curve2 as curve2 lazy.diag=True height = 70 width = 50 thickness = 30 # BASE pnt1 = point(-width/2,0,0); pnt2 = point(-width/2,-thickness/4,0); pnt3 = point(0,-thickness/2,0); pnt4 = point(width/2,-thickness/4,0); pnt5 = point(width/2,0,0); edge1 = segment(pnt1, pnt2) edge2 = circle_arc(pnt2, pnt3, pnt4) edge3 = segment(pnt4, pnt5) wire = sew([edge1, edge2, edge3]) profile = sew([wire, wire.mirrorX()]) body = profile.fill().extrude(height) body = fillet(body, thickness/12) hl(body.forw(140)) # NECK neck_radius = thickness/4.; neck_height = height/10; neck = cylinder(r=neck_radius, h=neck_height).up(height) body = body + neck hl(body.forw(100)) # THICK body = thicksolid(body, -thickness / 50, [point(0,0,height+height/10)]) hl(body.forw(60)) # THREAD ( 2       .) cylsurf1 = surface.cylinder(neck_radius * 0.99) cylsurf2 = surface.cylinder(neck_radius * 1.05) major = 2 * math.pi; minor = neck_height / 10; angle = math.atan2(neck_height / 4, 2 * math.pi) ellipse1 = curve2.ellipse(major, minor).rotate(angle) arc1 = cylsurf1.map(curve2.trimmed_curve2(ellipse1, 0, math.pi)) segment1 = cylsurf1.map(curve2.segment(ellipse1.value(0), ellipse1.value(math.pi))) ellipse2 = curve2.ellipse(major, minor/4).rotate(angle) arc2 = cylsurf2.map(curve2.trimmed_curve2(ellipse2, 0, math.pi)) segment2 = cylsurf2.map(curve2.segment(ellipse2.value(0), ellipse2.value(math.pi))) m1 = sew([arc1, segment1]) m2 = sew([arc2, segment2]) thread = loft([m1, m2]).up(height + neck_height / 2) hl(m1.up(height + neck_height / 2).right(80)) hl(m2.up(height + neck_height / 2).right(60)) hl(thread.right(40)) # FINAL m = thread + body display(m) show() 

bottle.png


Continuité de la tradition. L'origine comme source de tout


Les solutions de syntaxe zencad, à l'instar de son frère aîné et professeur OpenScad, minimisent le nombre d'entités dans la bibliothèque. Comme OpenScad, ZenCad est fondamentalement incapable de créer une primitive au point (x, y, z), malgré le fait qu'OpenCascade le permette. ZenCad crée d'abord une primitive à l'origine, puis définit la position dont il a besoin à l'aide de transformations. Les transformations dans ZenCad existent à la fois comme objets séparés et comme méthodes de corps.


 #  . cube(40, center=True).rotateX(deg(45)).rotateZ(deg(45)).right(20) #  . (right(20) * rotateZ(deg(45)) * rotateX(deg(45)))(cube(40, center=True)) #  . trans = right(20) * rotateZ(deg(45)) * rotateX(deg(45)) cube(40, center=True).transform(trans) 

Un ensemble de transformations est standard et comprend la translation, la rotation, la réflexion et le zoom.


La paresse


Afin de minimiser le temps de calcul, les calculs dans ZenCad sont lénifiés et tous les calculs sont agressivement mis en cache. La bibliothèque evalcache [del] blockchain [/ del], dont j'ai parlé il y a quelque temps sur les pages de Habrahabr, s'occupe de la gestion des algorithmes de lénification: mise en cache disque des arbres informatiques paresseux . Zencad enregistre les résultats des calculs dans un cache commun, dont l'état peut être surveillé via l'interface du visualiseur. L'algorithme de hachage sha512 utilisé avec une redondance marquée élimine la possibilité de collisions de clés de hachage pour les objets paresseux (l'espace de hachage est 10 ^ 74 fois le nombre d'atomes dans l'univers).


Lors de la création de ce modèle, il génère quatre mégaoctets de géométrie et lors de la première passe il peut être calculé assez longtemps:


bolt.png


Le travail avec des surfaces filetées est coûteux en calcul:


logo.png


Le problème de la topologie de réflexion. Méthode du point proche


OpenScad n'a aucune opération de chanfreinage ou d'arrondi. OpenCascade les fournit. Ce sont des opérations très importantes, et il serait dommage de ne pas les mettre en service pour ZenCad. Il existe d'autres opérations qui nécessitent de spécifier un objet topologique, par exemple, l'opération consistant à prendre un modèle à paroi mince dans l'exemple de bouteille OpenCascade. Dans un système de CAO graphique, nous indiquons un objet topologique (arête, face, sommet) avec la souris. Lors de l'écriture d'un script, nous n'avons pas une telle opportunité. Native OpenCascade résout le problème de la réflexion et l'utilise pour travailler avec la CAO graphique. Bien que ZenCad prenne en charge la réflexion du modèle, son utilisation comme outil principal présente un certain nombre d'inconvénients importants. Premièrement, le niveau de connaissance requis pour utiliser ces outils augmente fortement, car il faut au moins comprendre le concept topologique interne. Deuxièmement, dès qu'il apparaît dans le script, l'harmonie des algorithmes paresseux se casse immédiatement et le code du modèle est également assez compliqué. Au cours d'une réflexion et d'une expérimentation assez longues, j'ai opté pour la méthode du point proche. En bref, lors de l'exécution d'opérations dépendantes de la topologie, le programme contourne l'objet et trouve l'objet topologique le plus proche du point donné parmi ceux qui pénètrent dans le corps. Cet élément est considéré comme sélectionné. Une telle solution est plus coûteuse en termes de calcul, mais en raison de la mise en cache, elle fonctionne bien. Cette approche est utilisée pour toutes les opérations qui dépendent des éléments de topologie.


Comme déjà mentionné ci-dessus, la possibilité de refléter le modèle, par le bon sens, est également préservée, comme le montre l'exemple ci-dessus (Exemple: filtrage d'un tableau de points).


Marqueur Q et marqueur W


Les dimensions du modèle peuvent être difficiles à lire à l'écran en raison de la non-évidence de l'échelle. En partie, les marqueurs peuvent résoudre ce problème. Disposant d'une interface intuitive (nulle part plus intuitive), les marqueurs signalent les coordonnées et affichent la distance, ce qui simplifie l'analyse de la géométrie et la sélection des points pour des opérations telles que les chanfreins / arrondis.


marqueurs


Suivre les mises à jour des sources


Comme le grand frère (OpenScad), ZenCad est capable de mettre à jour le modèle généré lors de la modification du fichier source. En combinaison avec le système de mise en cache, cela vous permet de modifier très commodément le script, ayant sous vos yeux presque en temps réel l'état changeant du produit.


L'animation


Les mérites de zencad ne s'arrêtent pas là.


ZenCad (grâce à l'opencascade de base rapide) peut redessiner la scène en temps réel, ce qui vous permet d'animer un modèle 3D. L'animation est implémentée par une fonction python ordinaire et vous permet de vous faire plaisir en toute liberté. Étant donné que nous sommes dans un environnement python, zencad est capable de visualiser les données de sources externes sous forme de mouvements de modèle (par exemple, en utilisant le multithreading + tcpsocket). Ainsi, le zencad peut être utilisé, par exemple, pour des tests semi-naturels de produits robotiques. Oh bonjour Gazebo !!! Salut ROS !!! Je suis ravi de vous voir également dans le public. Une bibliothèque de cinématique, qui simplifierait considérablement la construction de chaînes cinématiques de manipulateurs robotiques, est d'ailleurs en cours de développement.


L'animation est pour l'instant encore en version semi-expérimentale (notamment en termes de contrôle de caméra) donc je ne m'attarderai pas là-dessus en détail.


Exporter - Importer


Actuellement, l'exportation et l'importation au format brep sont prises en charge, ce qui permet l'intégration avec freecad et l'exportation au format stl, ce qui permet de générer des modèles pour l'impression 3D. La génération de captures d'écran est également prise en charge. Y compris automatique. En particulier, les captures d'écran du manuel en ligne sont générées automatiquement par ZenCad.


Statut actuel


Pour le moment, ZenCad est encore très loin d'être achevé, et néanmoins il est pleinement opérationnel dans la partie dans laquelle il est prêt.


La bibliothèque est disponible en pipy pour les axes compatibles Debian avec les versions de python3.5, python3.6, python3.7


(Vous devrez peut-être installer qt5-default, en raison de certains problèmes avec les plugins dans PyQt5)


 python3 -m pip install zencad apt install qt5-default 

Exécuter gui à partir de la ligne de commande:


 python3 -m zencad 

Exécuter gui à partir d'un script python:


 #!/usr/bin/env python3 import zencad m = zencad.cube(20) zencad.disp(m) zencad.show() 

Malheureusement, les progrès du système ne vont pas aussi vite que nous le souhaiterions. La plupart des API de géométrie bidimensionnelle et des API de travail avec des surfaces n'ont pas encore été implémentées, la prise en charge de l'exportation et de l'importation de formats standard, la gestion des erreurs n'est pas toujours transparente, les tests automatiques n'ont pas été élaborés, des bibliothèques pour la construction de joints filetés et de produits d'engrenage ont été conçues et pas encore implémentées. En tant qu'éditeur externe, ce qui est complètement anormal, c'est soudainement hardcore !!! Sublime Text ... Je veux aussi vraiment affiner le système pour qu'il puisse être exécuté sous Windows (cela nécessite beaucoup de travail d'expertise).


Cependant, zencad vous permet désormais de concevoir des modèles 3D assez complexes, de créer des modèles pour l'impression 3D et même de visualiser la cinématique des mécanismes.


Liens du projet


github: https://github.com/mirmik/zencad , https://github.com/mirmik/servoce


pypi: https://pypi.org/project/zencad/ , https://pypi.org/project/pyservoce/


manuel


Merci de votre attention.


Source: https://habr.com/ru/post/fr443140/


All Articles