#5511: arbitrary mesh functions
-------------------------+--------------------------------------------------
 Reporter:  jason        |       Owner:  was       
     Type:  enhancement  |      Status:  new       
 Priority:  major        |   Milestone:  sage-3.4.1
Component:  graphics     |    Keywords:            
-------------------------+--------------------------------------------------
 The following worksheet implements arbitrary mesh functions for 3d
 graphics objects that are triangulated.  This could probably ought to go
 into sage somewhere:

 Arbitrary Mesh Functions
 system:sage

 {{{id=15|
 from sage.ext.fast_eval import fast_float
 ///
 }}}

 <p>Simple bisection root finder for a function of 3 variables.</p>

 {{{id=16|
 %hide
 %auto
 %cython

 cpdef find_root(f, double target, point_1, point_2, double epsilon=1e-4):
     """
     Given two 3d points point_1 and point_2, find a point (x,y,z) on the
 segment between them where abs(f(x,y,z)-target)<=epsilon.

     Returns (x,y,z) if the point lies on the segment between point_1 and
 point_2 and satisfies the above inequality, otherwise returns None.

     The code assumes the function f is continuous.
     """
     cdef double s0,s1,s2
     cdef double e0,e1,e2
     cdef double new_0,new_1,new_2
     cdef double target_0 = target-epsilon
     cdef double target_1 = target+epsilon
     cdef double val
     cdef int i

     cdef double min = f(*point_1)
     cdef double max = f(*point_2)
     s0,s1,s2 = point_1
     e0,e1,e2 = point_2
     if min>max:
         min,max=max,min
         s0,s1,s2,e0,e1,e2 = e0,e1,e2,s0,s1,s2
     # Check to see if one of the endpoints satisfies it
     if target_0<=min and min<=target_1:
         return (s0,s1,s2)
     if target_0<=max and max<=target_0:
         return (e0,e1,e2)
     if min>target_1 or max<target_0:
         return None
     i=0
     while True:
         if i>100:
             return None
         else:
             i+=1
         # Get half-way point
         new_0 = s0+(e0-s0)/2.0
         new_1 = s1+(e1-s1)/2.0
         new_2 = s2+(e2-s2)/2.0
         val = f(new_0, new_1, new_2)
         if val<target_0:
             s0, s1, s2 = new_0, new_1, new_2
             min = val
         elif target_1<val:
             e0, e1, e2 = new_0, new_1, new_2
             max=val
         else:
             return (new_0,new_1,new_2)
 ///
 }}}

 {{{id=24|

 ///
 }}}

 {{{id=41|
 def calculate_crossing(f,target,v0,v1,vertices, cache_dict):
     """
     Calculate, for an edge (v0,v1), where f is "close" to target.  Use
 cache_dict to cache the values.
     """
     # Make a canonical ordering of the vertices since (v0,v1) is the same
 edge as (v1,v0)
     if v0>v1:
         v0,v1=v1,v0
     if (v0,v1) in cache_dict:
         return cache_dict[(v0,v1)]
     else:
         pt = find_root(f, target, vertices[v0], vertices[v1])
         cache_dict[(v0,v1)]=pt
         return pt
 ///
 }}}

 {{{id=34|
 %time
 var('x,y,z')
 p=parametric_plot((x,y,9-x^2-y^2), (x,-3,3), (y,-3,3), mesh=True)
 f=x^2-sin(x*y^2)+cos(z)
 ff=fast_float(f, 'x', 'y','z')
 p.triangulate()
 vertices=p.vertex_list()

 # I am still calculating the function on each vertex multiple times; that
 could be optimized
 # vertex_values=[ff(*v) for v in vertices]

 mesh=[]
 for target in [0,2,..,20]:
     cache={}
     for face in [f+[f[0]] for f in p.index_faces()]:
         # Adding the [0] takes care of the edge from vertices[0] to
 vertices[-1]
         pts = [calculate_crossing(ff,target,face[i],
 face[i+1],vertices=vertices, cache_dict=cache) for i in
 range(len(face)-1)]
         pts = [i for i in pts if i is not None]
         mesh+=[line([pt1,pt2],thickness=3, color='black') for pt1,pt2 in
 Subsets(pts, 2)]
 ///

 CPU time: 0.91 s,  Wall time: 1.26 s
 }}}

 {{{id=39|
 p+sum(mesh)
 ///
 }}}

 {{{id=42|
 (p+sum(mesh)).show(viewer='tachyon')
 ///
 }}}

 {{{id=44|

 ///
 }}}

 {{{id=45|

 ///
 }}}

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/5511>
Sage <http://sagemath.org/>
Sage - Open Source Mathematical Software: Building the Car Instead of 
Reinventing the Wheel

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/sage-trac?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to