Author Topic: Hyperbolic Tessellation using C# .NET  (Read 16510 times)

0 Members and 1 Guest are viewing this topic.

vegbruiser

  • Guest
Re: Hyperbolic Tessellation using C# .NET
« Reply #15 on: January 17, 2012, 11:52:46 AM »
That's really cool! Thanks Kean.

The ability to select the {x,x} iterations would give the users the option of deciding how dense they want the resultant fill to be - is that a function you've built-in?

Kean

  • Newt
  • Posts: 48
Re: Hyperbolic Tessellation using C# .NET
« Reply #16 on: January 17, 2012, 11:54:31 AM »
Absolutely :)

Kean

  • Newt
  • Posts: 48
Re: Hyperbolic Tessellation using C# .NET
« Reply #17 on: January 20, 2012, 04:56:34 AM »

qjchen

  • Bull Frog
  • Posts: 285
  • Best wishes to all
Re: Hyperbolic Tessellation using C# .NET
« Reply #18 on: January 25, 2012, 08:37:44 AM »
Thank you Alex for this funny question.
and thanks Kean for your good .Net function.  I often read you blog and learn a lot from you, thank you Kean

Yesterday I read this topic and found it is a very funny question.
But when I dive into this question, it shocks me, it involves a lot of math problem.
Mobius inversion, Poincare disk, Hyperbolic geometry, symmetric group, .....
I have to read a lot of article to understand it.

Fortunately, I get know of it.
The following code is base on the compass and straightedge constructions (include inversion)
Now it is version 0.1. Can draw a lot of pattern. But duplicated polygon generated, I will improved it in the next version. Now you can use Express tool --overkill to remove this duplicated arcs.

One of my similar work- fractal tree
http://www.theswamp.org/index.php?topic=11255.msg142711#msg142711

Code - Auto/Visual Lisp: [Select]
  1. ;;; ========================================================================
  2. ;;; Some of the following code are writen by CHEN QING JUN                 ;
  3. ;;; Civil engineering Department, South China University of Technology     ;
  4. ;;; Purpose: To draw Hyperbolic Tessellation, just for fun                 ;
  5. ;;; The command name :test                                                 ;
  6. ;;; The platform: Acad2000 and after                                       ;
  7. ;;; Version: 1.0                                                           ;
  8. ;;; Limitation: Many duplication of arc, need to be overkill               ;
  9. ;;;             Will be improved in the following version                  ;
  10. ;;; Method: From the ideal of http://moniker.name/worldmaking/?p=385       ;
  11. ;;; 2012.01.25                                                             ;
  12. ;;; ========================================================================
  13.  
  14. (defun c:test( / layer mspace p q)
  15.  (prompt "\n Please note that the following (p-2)*(q-2) should be larger than 4 !")
  16.  (setq p (getint "\n The polygon size p=?:") q (getint "\n How many Polygon meet at one Vertex. q=?:") layer (getint "\n How many layer,it is better lower than 5, layer=?:"))
  17.  (if (or (null p) (null q) (null layer)) (setq p 5  q 4  layer 4 ))
  18.  (if (< (* (- p 2) (- q 2)) 4) (prompt "\n Sorry, you should change p and q")
  19.     (progn (q:entmake:circle (list 0 0 0) 1.0 "0" 1)
  20.     (makerepeat (DrawCenterPattern p q) layer))
  21.  )
  22.  (princ)
  23. )
  24.  
  25. ;;;Draw the Center Pattern
  26. (defun DrawCenterPattern(p q / c centerplst costheta d k p0 p0new p1new r resx s sintheta sx)
  27.  ;;This function comes from  http://moniker.name/worldmaking/?p=385
  28.  (setq s (sin (/ pi p)) sx (cos (/ pi p)) c (cos (/ pi q)))
  29.  (setq r (/ 1 (sqrt (- (/ (* c c) (* s s)) 1))))
  30.  (setq d (/ 1 (sqrt (- 1 (/ (* s s) (* c c))))))
  31.  (setq k (/ s sx))
  32.  ;;resx is the intersection of a line through origin and intersection with the inversion circle
  33.  (setq resx (q:alg:equation:2 (1+ (* k k)) (* -2 d) (- (* d d) (* r r))))
  34.  (setq p0 (list resx (* k resx) 0.))
  35.  (setq CenterPlst (cons p0 nil))
  36.  (setq sintheta (sin (/ (* 2 pi) p)) costheta (cos (/ (* 2 pi) p)))
  37.  (repeat (fix (1- p))
  38.   (setq p0new (car CenterPlst));;each new point
  39.   (setq p1new (list (- (* costheta (car p0new))(* sintheta (cadr p0new)))
  40.                     (+ (* sintheta (car p0new))(* costheta (cadr p0new)))
  41.               0.0)
  42.   );;Rotate p0new by angle (2pi/p)
  43.   (q:geo:drawPoinCareArc p0new p1new)
  44.   (setq CenterPlst (cons p1new CenterPlst))
  45.  )
  46.  (q:geo:drawPoinCareArc p1new p0);;Draw the Last hyperbolic line
  47.  CenterPlst
  48. )
  49.  
  50.  
  51. ;;;Recursive pattern draw, num is the layer definition
  52. (defun makerepeat(lst num / lst1)
  53.  (setq lst1 (q:list:dealRecur lst))
  54.  (if (> num 0)
  55.    (progn
  56.      (foreach x lst1
  57.        (setq res1 (q:geo:inversePlstto2P (cadr x) (car (car x)) (cadr (car x))))
  58.        (makerepeat res1 (1- num))
  59.      )
  60.    )
  61.  )
  62. )
  63.  
  64. ;; 2d Mirror Function a b defined the mirror line, c is the point to be mirrored
  65. (defun q:geo:mirrorp (a b c)
  66.   (polar a (- (angle a b) (- (angle a c) (angle a b))) (distance a c))
  67. )
  68.  
  69. ;;;;Inverst a Point List about a Hyperbolic line pa-pb Version 0.1
  70. ;;; Need to be Improved, An Important function of this code
  71. (defun q:geo:inversePlstto2P(plst pa pb / pav pcenter pnew res x)
  72.   (setq pav (q:geo:invert0 pa))
  73.   (setq res (list pb pa))
  74.   (if (< (q:vec:Length (q:vec:cross* pa pb)) 1e-7)
  75.    (progn
  76.      (foreach x plst
  77.          (setq pnew (q:geo:mirrorp pa pb x)
  78.                res (cons pnew res))
  79.          (q:geo:drawPoinCareArc (car res) (cadr res))
  80.      )
  81.    );;;This code deal with the line (pa,pb) pass origin
  82.    (progn
  83.      (setq pcenter (q:geo:circumcircle3d pa pb pav))
  84.      (foreach x plst
  85.          (setq pnew (q:geo:invert1 x (car pcenter) (cadr pcenter))
  86.                res (cons pnew res))
  87.          (q:geo:drawPoinCareArc (car res) (cadr res))
  88.      )
  89.      (q:geo:drawPoinCareArc (car res) (last res));;Draw the last arc
  90.    )
  91.   )
  92.   (reverse res)
  93. )
  94.  
  95.  
  96. ;;;A special List deal, Convert '(1 2 3 4 5 ) to
  97. ;;;(((1 2)(3 4 5)),((2 3)(4 5 1),((3 4)(5 1 2)),((4 5)(1 2 3)),((5 1)(2 3 4)))
  98. ;;;A rotation of the List, each contain (3 4) two element, and the other by order.
  99. (defun q:list:dealRecur(lst / i len lst3 res)
  100.  (if (<= (setq len (length lst)) 2) (setq res nil)
  101.    (progn
  102.     (setq lst (append lst lst) i 0)
  103.     (repeat len
  104.      (setq lst3 (list (list (nth i lst) (nth (1+ i) lst)) (q:list:N+num lst (+ i 2) (- len 2)))
  105.            res (cons lst3 res)
  106.            i (1+ i))
  107.     )
  108.    )
  109.  )
  110.  (reverse res)
  111. )
  112. ;;;;Draw Hyperbolic line in Poincare disk, Two Condition is consider
  113. (defun q:geo:drawPoinCareArc(pa pb / ang1 ang2 arcobj pav pcenter temp)
  114.  (setq pav (q:geo:invert0 pa))
  115.  (if (< (q:vec:Length (q:vec:cross* pa pb)) 1e-7)  ;;;Which means the line (pa,pb) go through origin
  116.     (vla-AddLine mSpace (vlax-3d-point pa)(vlax-3d-point pb))
  117.     (progn
  118.      (setq pcenter (q:geo:circumcircle3d pa pb pav)
  119.            ang1 (angle (car pcenter) pa)
  120.            ang2 (angle (car pcenter) pb))
  121.      (if (> ang1 ang2) (setq temp ang1 ang1 ang2 ang2 temp))
  122.      (if (> ang2 (+ pi ang1)) (setq temp ang1 ang1 ang2 ang2 temp))
  123.      (setq arcObj (vla-AddArc mSpace (vlax-3d-point (car pcenter)) (cadr pcenter) ang1 ang2))
  124.     )
  125.  )
  126. )
  127. ;;;Inverse a point to a unit circle
  128. (defun q:geo:invert0(p / d)
  129.  (setq d (distance p (list 0 0 0)))
  130.  (if (< d 1e-7) nil (q:vec:*c p (/ 1 d d)))
  131. )
  132. ;;;Inverse a point to a circle with center and radius r.
  133. (defun q:geo:invert1(p center r / d p1 p2)
  134.  (setq d (distance p center))
  135.  (if (< d 1e-7) nil
  136.    (progn (setq p1 (q:vec:- p center) p2 (q:vec:*c p1 (/ (* r r) d d )))
  137.     (q:vec:+ p2 center)
  138.    )
  139.  )
  140. )
  141. ;;;__________________________________________________________________;;
  142. ;;;General Function                                                  ;;
  143. ;;;__________________________________________________________________;;
  144. ;;;Get SubList of Lst from N to N+num
  145. (defun q:list:N+num(lst N num / c res)
  146.  (repeat N (setq lst (cdr lst)))
  147.  (repeat num (if (setq c (car lst)) (setq res (cons c res) lst (cdr lst))))
  148.  (reverse res)
  149. )
  150. ;;;Solve Quadratic Equations and Get Only the small one. Return nil if no solution
  151. (defun q:alg:equation:2(a b c)
  152.   (if (< (setq temp (- (* b b) (* a c 4.))) 0) nil
  153.   (/ (- 0 b (sqrt temp)) 2. a))
  154. )
  155. ;;entmake Circle
  156. (defun q:entmake:circle (center rad layer color)
  157.   (entmake (list (cons 0 "CIRCLE")(cons 6 "BYLAYER")
  158.   (cons 8 layer) (cons 10 center)(cons 40 rad)(cons 62 color)))
  159. )
  160. ;;;;vec plus
  161. (defun q:vec:+(v1 v2) (mapcar '+ v1 v2))
  162. ;;;;vec substract
  163. (defun q:vec:-(v1 v2) (mapcar '- v1 v2))
  164. ;;;;vec plus constant
  165. (defun q:vec:*c(v a)  (mapcar '(lambda(x) (* x a)) v))
  166. ;;;;vec dot product
  167. (defun q:vec:dot*(v1 v2) (apply '+ (mapcar '* v1 v2)))
  168. ;;;;vec cross product
  169. (defun q:vec:cross*(v1 v2)
  170.   (list (q:det:2 (cadr v1) (caddr v1) (cadr v2) (caddr v2))
  171.         (q:det:2 (caddr v1) (car v1) (caddr v2) (car v2))
  172.         (q:det:2 (car v1) (cadr v1) (car v2) (cadr v2)))
  173. )
  174. ;;;;Normalize a vec
  175. (defun q:vec:Norm(v / l)
  176.   (if (not (zerop (setq l (distance '(0 0 0) v))))
  177.   (mapcar '(lambda(x) (/ x l)) v))
  178. )
  179. ;;;; Vector Length
  180. (defun q:vec:Length(v) (sqrt (apply '+ (mapcar '(lambda(x) (expt x 2)) v))))
  181. ;;;;determinant library
  182. ;;;;cal determinant
  183. ;;;;|a1 a2|
  184. ;;;;|b1 b2|
  185. (defun q:det:2(a1 a2 b1 b2)
  186.   (- (* a1 b2) (* a2 b1))
  187. )
  188. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;Use Barycentric Coordinates to calculate multiple center
  189. ;;;http://mathworld.wolfram.com/BarycentricCoordinates.html
  190. ;;;http://en.wikipedia.org/wiki/Barycentric_coordinates_(mathematics)#Converting_to_barycentric_coordinates
  191. (defun q:geo:barycentric-normalize(a b c)
  192.   (mapcar '(lambda(x) (/ x (+ a b c))) (list a b c))
  193. )
  194. ;;;;transform from barycentric-to-Cartesian coordinate
  195. (defun q:geo:barycentric-to-Cartesian(tlst P1 P2 P3)
  196.  (q:vec:+  (q:vec:+ (q:vec:*c P1 (car tlst)) (q:vec:*c P2 (cadr tlst))) (q:vec:*c P3 (caddr tlst)))
  197. )
  198. ;;Find out the circumcircle of three point (three distinct, noncollinear WCS points)
  199. ;;;; qjchen@gmail.com
  200. (defun q:geo:circumcircle3d(p1 p2 p3 / a b c p temp)
  201.   (setq a (distance p2 p3) b (distance p1 p3) c (distance p1 p2))
  202.   (defun temp(a b c) (* a a (+ (* b b) (* c c) (* a (- a)))))
  203.   (setq p  (q:geo:barycentric-to-Cartesian (q:geo:barycentric-normalize (temp a b c) (temp b c a) (temp c a b)) P1 P2 P3))
  204.   (list p (distance p1 p))
  205. )
  206.  
  207.  
  208. (princ "\n By qjchen@gmail.com, Hyperbolic Tessellation. 1.0, The command is TEST")
  209.  

Some useful article for this problem
http://liris.cnrs.fr/david.coeurjolly/doku/code/poincare
https://svn.liris.cnrs.fr/dcoeurjo/Poincare/cairoPoincare.h
http://www.jasondavies.com/poincare-disc/
http://www.bugman123.com/Hyperbolic/index.html
http://zueuk.deviantart.com/gallery/
http://www.povray.org/
http://jsxgraph.uni-bayreuth.de/wiki/index.php/Poincare_disc_model
http://apps.hi.baidu.com/share/detail/34282038
http://zh.wikipedia.org/wiki/%E8%8E%AB%E6%AF%94%E4%B9%8C%E6%96%AF%E5%8F%98%E6%8D%A2
http://en.wikipedia.org/wiki/Poincar%C3%A9_disc_model
http://jsxgraph.uni-bayreuth.de/wiki/index.php/Category:Examples
http://moniker.name/worldmaking/?p=385
http://www.d.umn.edu/~ddunham/
http://www.google.com.hk/url?sa=t&rct=j&q=poincare+circle+hyperbolic+draw&source=web&cd=10&ved=0CIEBEBYwCQ&url=http%3A%2F%2Fcomp.uark.edu%2F~strauss%2Fpapers%2Fhypcomp.pdf&ctbs=sts%3A1&ei=o9AeT_i0EciXiAeG6YnaDQ&usg=AFQjCNG63EU4dQx9ahSPisDb5POtkao-OA&cad=rja
http://hyperart.cvs.sourceforge.net/viewvc/hyperart/hyperart/
http://www.rockini.name/gallery00.php


« Last Edit: January 25, 2012, 08:45:52 AM by qjchen »
http://qjchen.mjtd.com
My blog http://chenqj.blogspot.com (Chinese, can be translate into English)

vegbruiser

  • Guest
Re: Hyperbolic Tessellation using C# .NET
« Reply #19 on: January 25, 2012, 08:58:20 AM »
That's a pretty comprehensive list of links, thanks!

:)

I'm in the process of converting Kean's .NET classes to use in Inventor. Wish me luck!

qjchen

  • Bull Frog
  • Posts: 285
  • Best wishes to all
Re: Hyperbolic Tessellation using C# .NET
« Reply #20 on: January 25, 2012, 09:03:13 AM »
That's a pretty comprehensive list of links, thanks!

:)

I'm in the process of converting Kean's .NET classes to use in Inventor. Wish me luck!

Best wishes :), I am sure you could convert Kean's code to Inventor, then you could do wonderful 3d artworks~  :-)
http://qjchen.mjtd.com
My blog http://chenqj.blogspot.com (Chinese, can be translate into English)

vegbruiser

  • Guest
Re: Hyperbolic Tessellation using C# .NET
« Reply #21 on: January 25, 2012, 09:15:14 AM »
the ultimate goal is to create this kind of pattern in 3D and use it as a sub-structure within parts that are destined to be 3D Printed.

So far, I've been able to create the following part in Inventor: (See attached)

EDIT for clarity: This part was created by importing the hyperbolic geometry created in AutoCAD into Inventor's sketch environment.

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: Hyperbolic Tessellation using C# .NET
« Reply #22 on: January 26, 2012, 01:19:40 AM »
Thank you! Very interesting topic...
I think the proposed way to reduce the amount of material for 3D printing is too complicated! I suggest using the triangle (tetrahedron) or squares (cubes).

vegbruiser

  • Guest
Re: Hyperbolic Tessellation using C# .NET
« Reply #23 on: January 26, 2012, 03:32:19 AM »
Evgeniy, you are correct that this is complicated, but I don't think it's overly complex - at least not when compared to how nature does it. (think bird skulls/bones etc.)

The use of hyperbolic tessellation (regardless of what {x,x} iterations you use) is one way to provide a good blend of material saving and strength. (At least until I or someone else can test it and prove otherwise)

qjchen

  • Bull Frog
  • Posts: 285
  • Best wishes to all
Re: Hyperbolic Tessellation using C# .NET
« Reply #24 on: January 26, 2012, 09:15:12 AM »
Thank you, Alex, for your beautiful Inventor pattern picture.~
And thanks Evgeniy for this beautiful Euclidean Recursive Picture.
http://qjchen.mjtd.com
My blog http://chenqj.blogspot.com (Chinese, can be translate into English)

vegbruiser

  • Guest
Re: Hyperbolic Tessellation using C# .NET
« Reply #25 on: February 07, 2012, 08:23:32 AM »
I now have a (more-or-less) working native-Inventor implementation of the code provided by Kean.

There are still a few issues surrounding the number of lines produced when creating each polygon - namely that each line (up to but not including the outer "layer") is part of 2 polygons, therefore you end up with twice as many lines as are required.

And I also need to look again at the setup dialogues - currently (And I can only assume because something got lost in the translation from C# to VB.NET) I can only pick 7-sided polygons with 3 meeting at each intersection and > 2 layers.

Ideally I think I'd want to emulate as closely as possible the fine degree of control afforded by Kean's solution.

Anyway, here's my code:

(See attached.)