tikz.within( '*' ) local cos = math.cos local sin = math.sin local pi = math.pi -- granularity of calculation local fine = 10 -- factor the projection length is reduced local fproj = 0.35 -- strength of the ellipse mediums local s1 = 1.00 local s2 = 1.50 local s3 = 1.75 local e1 = ellipse{ at=p{ 0.00, 0.00 }, xradius=3.00, yradius=3.00 } local e2 = ellipse{ at=p{ 0.40, 1.20 }, xradius=0.85, yradius=0.50 } local e3 = ellipse{ at=p{ 0.00, -0.89 }, xradius=1.00, yradius=0.60 } draw{ fill='black!08!white', line_width=1, e1 } draw{ fill='black!16!white', line_width=1, e2 } draw{ fill='black!24!white', line_width=1, e3 } -- list of projection angles local listphi = { -1/4 * pi, 2/4 * pi, 5/4 * pi, } -- length of projection lines local lenmaintop = 5.0 local lenmainbot = 6.5 for proji, phimain in ipairs( listphi ) do local lmain = line{ p{ cos( phimain ), sin( phimain ) } * -lenmaintop, p{ cos( phimain ), sin( phimain ) } * lenmainbot, } local phinorm = phimain - pi/2 -- gets a point on the projection. -- dp: distance from projection center -- dv: projection value function getpproj( dp, dv ) return( lmain.p2 + p{ cos( phinorm ) * dp, sin( phinorm ) * dp } + p{ cos( phimain ) * dv * fproj, sin( phimain ) * dv * fproj } ) end -- distance of projection line local ddis = 1 / fine -- list of all projection points local listp = { } for i = -3.5 * fine, 3.5 * fine do local p1i = lmain.p1 + p{ cos( phinorm ) * ddis * i, sin( phinorm ) * ddis * i } local li = line{ p1i, p1i + ( lmain.p2 - lmain.p1 ) } local lv = 0 local is1 = e1.intersectLine( li ) if is1 and #is1 > 1 then local lis = line{ is1[ 1 ], is1[ 2 ] } lv = lv + lis.length * s1 end local is2 = e2.intersectLine( li ) if is2 and #is2 > 1 then local lis = line{ is2[ 1 ], is2[ 2 ] } lv = lv + lis.length * s2 end local is3 = e3.intersectLine( li ) if is3 and #is3 > 1 then local lis = line{ is3[ 1 ], is3[ 2 ] } lv = lv + lis.length * s3 end local pproj = getpproj( ddis * i, lv ) if i % ( 0.7 * fine ) == 0 then draw{ dotted, arrow, line_width=0.5, line{ li.p1, getpproj( ddis * i, -0.20 ) }, } draw{ dotted, line_width=0.5, line{ li.p1, pproj }, } end table.insert( listp, pproj ) end -- draws the projection screen local lenlproj = 8 draw{ line{ getpproj( lenlproj / 2, 0 ), getpproj( -lenlproj / 2, 0 ), } } -- draws the projection curve draw{ line_width=1, polyline{ table.unpack( listp ) } } end