#+TITLE: Mesh.org #+AUTHOR: screwtape * gmsh sphere geometry utility #+BEGIN_EXAMPLE I just got into 3D printing. I'm not this doesn't produce; your slicer interested in downloading others' probably can add that automatically. stuff in general, I want to make The program is basically a poor stuff. Rather than thinking through man's macro system inside CLOS extrusions, I had the idea to simply methods so as to use class scope csg-sum unit spheres at different allocated indices to create a scales and positions (using gmsh combined geometry file output. It which uses oce). The lowest surfaces adds spheres don't worry about it. of a sphere generally need supports #+END_EXAMPLE ** Geometry of two overlapping spheres #+name: twospheres #+begin_src lisp :noweb yes :results output <> (defvar *aball* (make-instance 'sphere :x 0 :y 0 :z 0 :r 10 :lc 5)) (defvar *bball* (make-instance 'sphere :x 10 :y 0 :z 0 :r 10 :lc 5)) (geo-beginning *aball*) (fill-forms *aball*) (fill-forms *bball*) (mapc 'eval (forms *aball*)) (mapc 'eval (forms *bball*)) #+end_src #+RESULTS: twospheres #+begin_example Mesh.Algorithm = 6; lc = 5; Point(1) = {0,0,0,lc}; Point(2) = {10,0,0,lc}; Point(3) = {0,10,0,lc}; Circle(1) = {2,1,3}; Point(4) = {-10,0,0,lc}; Point(5) = {0,-10,0,lc}; Circle(2) = {3,1,4}; Circle(3) = {4,1,5}; Circle(4) = {5,1,2}; Point(6) = {0,0,-10,lc}; Point(7) = {0,0,10,lc}; Circle(5) = {3,1,6}; Circle(6) = {6,1,5}; Circle(7) = {5,1,7}; Circle(8) = {7,1,3}; Circle(9) = {2,1,7}; Circle(10) = {7,1,4}; Circle(11) = {4,1,6}; Circle(12) = {6,1,2}; Curve Loop(13) = {2,8,-10}; Surface(14) = {13}; Curve Loop(15) = {10,3,7}; Surface(16) = {15}; Curve Loop(17) = {-8,-9,1}; Surface(18) = {17}; Curve Loop(19) = {-11,-2,5}; Surface(20) = {19}; Curve Loop(21) = {-5,-12,-1}; Surface(22) = {21}; Curve Loop(23) = {-3,11,6}; Surface(24) = {23}; Curve Loop(25) = {-7,4,9}; Surface(26) = {25}; Curve Loop(27) = {-4,12,-6}; Surface(28) = {27}; Surface Loop(29) = {28,26,16,14,20,24,22,18}; Volume(30) = {29}; Physical Surface(1) = {28,26,16,14,20,24,22,18}; Physical Volume(2) = {30}; Point(8) = {10,0,0,lc}; Point(9) = {20,0,0,lc}; Point(10) = {10,10,0,lc}; Circle(31) = {9,8,10}; Point(11) = {0,0,0,lc}; Point(12) = {10,-10,0,lc}; Circle(32) = {10,8,11}; Circle(33) = {11,8,12}; Circle(34) = {12,8,9}; Point(13) = {10,0,-10,lc}; Point(14) = {10,0,10,lc}; Circle(35) = {10,8,13}; Circle(36) = {13,8,12}; Circle(37) = {12,8,14}; Circle(38) = {14,8,10}; Circle(39) = {9,8,14}; Circle(40) = {14,8,11}; Circle(41) = {11,8,13}; Circle(42) = {13,8,9}; Curve Loop(43) = {32,38,-40}; Surface(44) = {43}; Curve Loop(45) = {40,33,37}; Surface(46) = {45}; Curve Loop(47) = {-38,-39,31}; Surface(48) = {47}; Curve Loop(49) = {-41,-32,35}; Surface(50) = {49}; Curve Loop(51) = {-35,-42,-31}; Surface(52) = {51}; Curve Loop(53) = {-33,41,36}; Surface(54) = {53}; Curve Loop(55) = {-37,34,39}; Surface(56) = {55}; Curve Loop(57) = {-34,42,-36}; Surface(58) = {57}; Surface Loop(59) = {58,56,46,44,50,54,52,48}; Volume(60) = {59}; Physical Surface(3) = {58,56,46,44,50,54,52,48}; Physical Volume(4) = {60}; #+end_example #+BEGIN_EXAMPLE Output to a geo file can be opened in gmsh, and then mesh>3D'd. Everything could be better! #+END_EXAMPLE ** Source #+name: mesh #+begin_src lisp (defpackage mesh (:use cl) (:export sphere geo-beginning fill-forms)) (in-package mesh) (defclass 3d () ((points :initform nil :accessor points) (lc :initarg :lc :reader lc) (complexes :initform nil :accessor complexes) (phys :initform nil :accessor phys) (surface :accessor surface) (volume :accessor volume) (next-point :allocation :class) (next-phy :allocation :class) (next-complex :allocation :class)) (:default-initargs :lc 5)) (defmethod new-pnt ((obj 3d)) " (new-pnt 3D) Adds a class-scope new point. " (let ((idx (incf (slot-value obj 'next-point)))) (if (null (points obj)) (setf (points obj) (list idx)) (nconc (points obj) (list idx))) (values idx))) (defmethod pof ((obj 3d) n) " (pof 3d x) Gets the locally scoped (1- x) indexed point " (nth (1- n) (points obj))) (defmethod cof ((obj 3d) n) " (cof 3d x) Gets the locally scoped (1- x) indexed complex " (nth (1- n) (complexes obj))) (defmethod new-phy ((obj 3d)) " (new-phy 3d) Adds a class-scope physical object " (let ((idx (incf (slot-value obj 'next-phy)))) (if (null (phys obj)) (setf (phys obj) (list idx)) (nconc (phys obj) (list idx))) (values idx))) (defmethod new-cpx ((obj 3d)) " (new-cpx 3d) Adds a class-scope complex object " (let ((idx (incf (slot-value obj 'next-complex)))) (if (null (complexes obj)) (setf (complexes obj) (list idx)) (nconc (complexes obj) (list idx))) (values idx))) (defmethod shared-initialize :after ((obj 3d) names &rest args) (declare (ignore names args)) (unless (slot-boundp obj 'next-point) (setf (slot-value obj 'next-point) 0 (slot-value obj 'next-complex) 0 (slot-value obj 'next-phy) 0))) (defclass sphere (3d) ((x :initarg :x :accessor x) (y :initarg :y :accessor y) (z :initarg :z :accessor z) (r :initarg :r :accessor r) (sphere-forms :type list :initform (list) :accessor forms)) (:documentation " (make-instance mesh:sphere :x 3 :y 4 :z 5 :r 10 :lc 3) Instantiates an object for the printing of a gmsh geometry of said sphere equivalent to gmsh's unit sphere (but with class scope indices) ")) (defun blank () '(format t "~%")) (defmethod add-point ((obj 3d) x y z) (let ((p (new-pnt obj))) `(format t "Point(~d) = {~d,~d,~d,lc};~%" ,p ,x ,y ,z))) (defmethod add-circle ((obj 3d) a b c &aux (p (pof obj a)) (q (pof obj b)) (r (pof obj c))) (let ((s (new-cpx obj))) `(format t "Circle(~d) = {~d,~d,~d};~%" ,s ,p ,q ,r))) (defun sgn (n) (if (plusp n) 1 -1)) (defmethod add-curvel ((obj 3d) a b c &aux (p (* (sgn a) (cof obj (abs a)))) (q (* (sgn b) (cof obj (abs b)))) (r (* (sgn c) (cof obj (abs c))))) (let ((s (new-cpx obj))) `(format t "Curve Loop(~d) = {~d,~d,~d};~%" ,s ,p ,q ,r))) (defmethod add-surface ((obj 3d) x) (let ((s (new-cpx obj))) `(format t "Surface(~d) = {~d};~%" ,s ,(cof obj x)))) (defmethod add-volume ((obj 3d) x) (let ((s (new-cpx obj))) `(format t "Volume(~d) = {~d};~%" ,s ,(cof obj x)))) (defmethod add-surfl ((obj 3d) &rest args) (let ((s (new-cpx obj)) (new-args (mapcar (lambda (x) (cof obj x)) args))) `(format t "Surface Loop(~d) = {~@{~d~^,~}};~%" ,s ,@new-args))) (defmethod phy-surf ((obj 3d) &rest args) (let ((s (new-phy obj)) (new-args (mapcar (lambda (x) (cof obj x)) args))) `(format t "Physical Surface(~d) = {~@{~d~^,~}};~%" ,s ,@new-args))) (defmethod phy-vol ((obj 3d) vol) (let ((s (new-phy obj))) `(format t "Physical Volume(~d) = {~d};~%" ,s ,(cof obj vol)))) (defmethod geo-beginning ((obj sphere) &aux (mesh-algo 6) (lc (lc obj))) (setf (forms obj) (list `(format t "~a = ~d;~%" "Mesh.Algorithm" ,mesh-algo) (blank) `(format t "lc = ~d;~%" ,lc)))) (defmethod fill-forms ((obj sphere) &aux (x (x obj)) (y (y obj)) (z (z obj)) (r (r obj)) (lc (lc obj))) " (fill-forms sphere) Prints the Gmsh geometry of a unit sphere at (x sphere) .. of radius/lc (r sphere) (lc sphere) Exactly equivalent to the the unit sphere from gmsh. The point / extrusion / physical counters are class scope so subsequent mesh::3d instances can be printed in the same geometry. 'complexes' is an erroneous name. " (setf (forms obj) (nconc (forms obj) (list (add-point obj x y z) (add-point obj (+ x r) y z) (add-point obj x (+ y r) z) (add-circle obj 2 1 3) (add-point obj (- x r) y z) (add-point obj x (- y r) z) (add-circle obj 3 1 4) ; 10 (add-circle obj 4 1 5) (add-circle obj 5 1 2) (add-point obj x y (- z r)) (add-point obj x y (+ z r)) ; 14 (add-circle obj 3 1 6) (add-circle obj 6 1 5) (add-circle obj 5 1 7) (add-circle obj 7 1 3) (add-circle obj 2 1 7) (add-circle obj 7 1 4) (add-circle obj 4 1 6) (add-circle obj 6 1 2) ; 22 (add-curvel obj 2 8 -10) (add-surface obj 13) (add-curvel obj 10 3 7) (add-surface obj 15) (add-curvel obj -8 -9 1) (add-surface obj 17) ; 28 (add-curvel obj -11 -2 5) (add-surface obj 19) (add-curvel obj -5 -12 -1) (add-surface obj 21) (add-curvel obj -3 11 6) (add-surface obj 23) (add-curvel obj -7 4 9) (add-surface obj 25) (add-curvel obj -4 12 -6) (add-surface obj 27) ; 38 (add-surfl obj 28 26 16 14 20 24 22 18) (add-volume obj 29) (blank) (phy-surf obj 28 26 16 14 20 24 22 18) (phy-vol obj 30) (blank))))) #+end_src