Advertisement
anilshanbhag

VER 2

Jun 13th, 2011
186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 14.34 KB | None | 0 0
  1. #!/usr/bin/python
  2. #GSoC Logic Implementation
  3. from math import *
  4. import cairo
  5.  
  6. #Corner and Side indices
  7. c_tl=0
  8. c_tr=1
  9. c_br=2
  10. c_bl=3
  11.  
  12. side_top=0
  13. side_right=1
  14. side_bottom=2
  15. side_left=3
  16.  
  17. #Input Parameters
  18. width=800.0
  19. height=600.0
  20. sides=[width,height,width,height]
  21. borderSizes=[50.0,50.0,50.0,50.0]
  22. borderRadii=[[300.0,300.0],[100.0,100.0],[100.0,100.0],[100.0,100.0]]
  23. delta=1.0 #Angle Increment
  24.  
  25. #Computed Parameters
  26. innerRadii=[[0,0],[0,0],[0,0],[0,0]]
  27.  
  28. #Cairo initialization
  29. surface = cairo.ImageSurface (cairo.FORMAT_ARGB32,int(width), int(height))
  30. ctx = cairo.Context (surface)
  31. ctx.scale (width,height)
  32.  
  33. def EllipseE(k,ph2,ph1=0.0):
  34.     """Computes the elliptic integral second kind : Integral from ph1 to ph2 of sqrt (1-k*sinSquare(phi))
  35.     Uses Simpson's 3/8 rule : gives result correctly approxiamted to one decimal place
  36.     Furthur Reading :http://en.wikipedia.org/wiki/Simpson's_rule"""
  37.     def func(x,t):
  38.         return sqrt(1-x*sin(t)*sin(t))
  39.     return abs(ph2-ph1)/8*(func(k,ph1)+3*func(k,(2*ph1+ph2)/3)+3*func(k,(ph1+2*ph2)/3)+func(k,ph2))
  40.  
  41. def absToParam(ta,a,b):
  42.     """Absolute to Parametric angle"""
  43.     return atan(b*tan(ta)/a)
  44.  
  45. def paramToAbs(tp,a,b):
  46.     """Parametric to Absolute angle"""
  47.     return atan(a*tan(tp)/b)
  48.  
  49. def ComputeCurvedLength(sideIndex,cornerIndex):
  50.     """Computes the length to be included in gap width calculation"""
  51.     #       .________<-side under consideration
  52.     #     /|
  53.     #    / |a
  54.     #   /__|
  55.     #   |b
  56.     #t is the demarcating angle
  57.     #T is parametric angle of point which seperates the sections of curve
  58.     #a is radii of ellipse [central ellipse] adjacent to side under consideration  
  59.     #b is the other radii
  60.      
  61.     a = (borderRadii[cornerIndex][1-sideIndex%2]+innerRadii[cornerIndex][1-sideIndex%2])/2
  62.     b = (borderRadii[cornerIndex][sideIndex%2]+innerRadii[cornerIndex][sideIndex%2])/2
  63.     t = (borderSizes[sideIndex]/(borderSizes[sideIndex]+borderSizes[(sideIndex-1)%4]))*(pi/2) if sideIndex==cornerIndex else (borderSizes[sideIndex]/(borderSizes[sideIndex]+borderSizes[(sideIndex+1)%4]))*(pi/2)
  64.    
  65.     #Calculation ::
  66.     #There exist 2 cases : When major axis along x axis or along y axis
  67.     #In general if R,r are length of semi major axis and semi minor axis
  68.     #Ray at angle t intersects ellipse at a point which satisties y = x*tant
  69.     #Also point x,y can be written as RcosT,rsinT where T is the paramteric angle  
  70.    
  71.     if a>=b:
  72.         T = atan((a/b)*tan(t)) 
  73.         k = 1-(b/a)**2
  74.         return a*EllipseE(k,T)
  75.     else:
  76.         T = atan(b/(a*tan(t)))
  77.         k = 1-(a/b)**2
  78.         return b*EllipseE(k,pi/2,T)
  79.    
  80. def calculateDashes(sideIndex):
  81.     """For a particular side computes the [dash width,gap width,offsetRaw] for that side """
  82.     dashWidth = 2*borderSizes[sideIndex]
  83.    
  84.     #Straight Path Length
  85.     straightLength = sides[sideIndex] - borderRadii[sideIndex][sideIndex%2] - borderRadii[(sideIndex+1)%4][sideIndex%2]
  86.    
  87.     #1->Left of side
  88.     curvedLength1 = ComputeCurvedLength(sideIndex,sideIndex)
  89.    
  90.     #2->Right of side
  91.     curvedLength2 = ComputeCurvedLength(sideIndex,(sideIndex+1)%4)
  92.  
  93.     totalLength = straightLength + curvedLength1 + curvedLength2
  94.    
  95.     # The totalLength = n * (dash length + gap length)
  96.     # The constrain on 0.5*dashWidth <= gapWidth <= dashWidth : for a range the lowest value chosen
  97.     n=floor(totalLength/(1.5*dashWidth))
  98.     gapWidth = totalLength/n - dashWidth
  99.    
  100.     # Calculate offset for dash pattern
  101.     # This is for the offset parameter in ctx.set_dash
  102.     if(curvedLength1<dashWidth/2):
  103.         offset=curvedLength1
  104.     else:
  105.         offset=(curvedLength1 -dashWidth/2) - floor((curvedLength1-dashWidth/2)/(dashWidth+gapWidth))*(dashWidth+gapWidth)
  106.    
  107.     return [dashWidth,gapWidth,offset]
  108.  
  109. def drawStraightSection(sideIndex,dashes,offset):  
  110.     """ Draws the straight section of given side """
  111.     if(sideIndex == side_top):
  112.         [startX,startY,endX,endY] = [0.0+borderRadii[c_tl][0],0.0+borderSizes[sideIndex]/2,
  113.                                      width-borderRadii[c_tr][0],0.0+borderSizes[sideIndex]/2]
  114.     elif(sideIndex == side_right):
  115.         [startX,startY,endX,endY] = [width-(borderSizes[sideIndex]/2),0.0+borderRadii[c_tr][1],
  116.                                      width-(borderSizes[sideIndex]/2),height-borderRadii[c_br][1]]
  117.     elif(sideIndex == side_bottom):
  118.         [startX,startY,endX,endY] = [width-borderRadii[c_br][0],height-(borderSizes[sideIndex]/2),
  119.                                      0.0+borderRadii[c_bl][0],height-(borderSizes[sideIndex]/2)]
  120.     elif(sideIndex == side_left):
  121.         [startX,startY,endX,endY] = [0.0+(borderSizes[sideIndex]/2),height-borderRadii[c_bl][1],
  122.                                      0.0+(borderSizes[sideIndex]/2),0.0+borderRadii[c_tl][1]]
  123.     else:
  124.         print "Some error crept in DRAW SIDE : INDEX"
  125.    
  126.     #Reducing to range 0,1 for cairo   
  127.     [startX,startY,endX,endY] = [startX/width,startY/height,endX/width,endY/height]
  128.    
  129.     #Draw!
  130.     ctx.save()
  131.     ctx.move_to(startX,startY)
  132.     ctx.line_to(endX,endY)
  133.     ctx.set_source_rgb (1.0, 0.0, 0.0) # Solid color
  134.     ctx.set_line_width (borderSizes[sideIndex]/sides[(sideIndex+1)%4])
  135.     ctx.set_dash(dashes,offset)
  136.     ctx.stroke()
  137.     ctx.restore()
  138.  
  139. def drawCCW(corner,dash,gap):
  140.     """Draws section of corner in counter clockwise sense """
  141.    
  142.     if corner == 0: [cornerOffsetX,cornerOffsetY] = borderRadii[0]
  143.     elif corner == 1: [cornerOffsetX,cornerOffsetY] = [width - borderRadii[1][0],borderRadii[1][1]]
  144.     elif corner == 2: [cornerOffsetX,cornerOffsetY] = [width-borderRadii[2][0],height-borderRadii[2][1]]  
  145.     elif corner == 3: [cornerOffsetX,cornerOffsetY] = [borderRadii[3][0],height - borderRadii[3][1]]
  146.    
  147.     ctx.save()
  148.     ctx.translate(cornerOffsetX/width,cornerOffsetY/height) # Move to corner center
  149.     ctx.transform(cairo.Matrix(1,0,0,-1,0,0)) # Flip Y Axis
  150.    
  151.     oCurveDims = borderRadii[corner]
  152.     iCurveDims = innerRadii[corner]
  153.     curveDims = [(oCurveDims[0]+iCurveDims[0])/2,(oCurveDims[1]+iCurveDims[1])/2]
  154.    
  155.     #Start Angle [0,pi/2]
  156.     start = (borderSizes[corner]/(borderSizes[(corner-1)%4]+borderSizes[corner]))*pi/2
  157.    
  158.     #End Angle [0,2*pi]
  159.     endAngle = (2-corner)%4 * pi/2
  160.     if endAngle == 0:
  161.         endAngle = 2*pi
  162.    
  163.     #Start angle [0,2*pi]
  164.     startAngle = endAngle - pi/2 + absToParam(start,curveDims[(corner+1)%2],curveDims[corner%2])
  165.                                    
  166.     current = startAngle
  167.     previous = current
  168.  
  169.     currentO = endAngle - pi/2 + absToParam(start,oCurveDims[(corner+1)%2],oCurveDims[corner%2])
  170.     previousO = currentO
  171.  
  172.     currentI = endAngle - pi/2 + absToParam(start,iCurveDims[(corner+1)%2],iCurveDims[corner%2])
  173.     previousI = currentI
  174.    
  175.     [R,r] = curveDims if curveDims[0]>curveDims[1] else [curveDims[1],curveDims[0]]
  176.     k = 1- r**2/R**2
  177.     curlen = 0.0
  178.     flag = 0.0
  179.    
  180.     while curlen<dash/2:
  181.         current += delta*pi/180
  182.         curlen += R*EllipseE(k,current,current-delta*pi/180.0)
  183.    
  184.     if current>endAngle:
  185.         current=endAngle
  186.         flag=1
  187.            
  188.     currentO = absToParam(paramToAbs(current - (endAngle - pi/2),curveDims[(corner+1)%2],curveDims[corner%2]),oCurveDims[(corner+1)%2],oCurveDims[corner%2]) + endAngle - pi/2
  189.     currentI = absToParam(paramToAbs(current - (endAngle - pi/2),curveDims[(corner+1)%2],curveDims[corner%2]),iCurveDims[(corner+1)%2],iCurveDims[corner%2]) + endAngle - pi/2
  190.  
  191.     stepO = (currentO - previousO)/30
  192.     stepI = (currentI - previousI)/30
  193.    
  194.     ctx.move_to(oCurveDims[0]*cos(previousO)/width,oCurveDims[1]*sin(previousO)/height)
  195.  
  196.     for i in range(1,31):
  197.         ctx.line_to(oCurveDims[0]*cos(previousO+stepO*i)/width,oCurveDims[1]*sin(previousO+stepO*i)/height)
  198.    
  199.     ctx.line_to(iCurveDims[0]*cos(currentI)/width,iCurveDims[1]*sin(currentI)/height)
  200.    
  201.     for i in range(1,31):
  202.         ctx.line_to(iCurveDims[0]*cos(currentI-stepI*i)/width,iCurveDims[1]*sin(currentI-stepI*i)/height)
  203.    
  204.     ctx.close_path()
  205.     ctx.fill()
  206.     previous = current
  207.     curlen=0
  208.    
  209.     if flag:
  210.         return
  211.    
  212.     while True:
  213.         while curlen<gap:
  214.             current += delta*pi/180
  215.             curlen += R*EllipseE(k,current,current-delta*pi/180)
  216.        
  217.         previous = current
  218.         currentO = absToParam(paramToAbs(current - (endAngle - pi/2),curveDims[(corner+1)%2],curveDims[corner%2]),oCurveDims[(corner+1)%2],oCurveDims[corner%2]) + endAngle - pi/2
  219.         currentI = absToParam(paramToAbs(current - (endAngle - pi/2),curveDims[(corner+1)%2],curveDims[corner%2]),iCurveDims[(corner+1)%2],iCurveDims[corner%2]) + endAngle - pi/2
  220.         previousO = currentO
  221.         previousI = currentI
  222.         curlen=0
  223.         if current>endAngle:
  224.             break  
  225.         while curlen<dash:
  226.             current += delta*pi/180
  227.             curlen += R*EllipseE(k,current,current-delta*pi/180.0)
  228.        
  229.         if current>endAngle:
  230.             current=endAngle
  231.             flag=1
  232.                
  233.         currentO = absToParam(paramToAbs(current - (endAngle - pi/2),curveDims[(corner+1)%2],curveDims[corner%2]),oCurveDims[(corner+1)%2],oCurveDims[corner%2]) + endAngle - pi/2
  234.         currentI = absToParam(paramToAbs(current - (endAngle - pi/2),curveDims[(corner+1)%2],curveDims[corner%2]),iCurveDims[(corner+1)%2],iCurveDims[corner%2]) + endAngle - pi/2
  235.    
  236.         stepO = (currentO - previousO)/30
  237.         stepI = (currentI - previousI)/30
  238.        
  239.         ctx.move_to(oCurveDims[0]*cos(previousO)/width,oCurveDims[1]*sin(previousO)/height)
  240.    
  241.         for i in range(1,31):
  242.             ctx.line_to(oCurveDims[0]*cos(previousO+stepO*i)/width,oCurveDims[1]*sin(previousO+stepO*i)/height)
  243.        
  244.         ctx.line_to(iCurveDims[0]*cos(currentI)/width,iCurveDims[1]*sin(currentI)/height)
  245.        
  246.         for i in range(1,31):
  247.             ctx.line_to(iCurveDims[0]*cos(currentI-stepI*i)/width,iCurveDims[1]*sin(currentI-stepI*i)/height)
  248.        
  249.         ctx.close_path()
  250.         ctx.fill()
  251.         previous = current
  252.         curlen=0
  253.        
  254.         if flag:
  255.             break
  256.            
  257.     ctx.restore()
  258.  
  259. def drawCW(corner,dash,gap):
  260.     if corner == 0: [cornerOffsetX,cornerOffsetY] = borderRadii[0]
  261.     elif corner == 1: [cornerOffsetX,cornerOffsetY] = [width - borderRadii[1][0],borderRadii[1][1]]
  262.     elif corner == 2: [cornerOffsetX,cornerOffsetY] = [width-borderRadii[2][0],height-borderRadii[2][1]]  
  263.     elif corner == 3: [cornerOffsetX,cornerOffsetY] = [borderRadii[3][0],height - borderRadii[3][1]]
  264.    
  265.     ctx.save()
  266.     ctx.translate(cornerOffsetX/width,cornerOffsetY/height) # Move to corner center
  267.     ctx.transform(cairo.Matrix(1,0,0,-1,0,0)) # Flip Y Axis
  268.    
  269.     oCurveDims = borderRadii[corner]
  270.     iCurveDims = innerRadii[corner]
  271.     curveDims = [(oCurveDims[0]+iCurveDims[0])/2,(oCurveDims[1]+iCurveDims[1])/2]
  272.    
  273.     #Start Angle [0,pi/2]
  274.     start = (borderSizes[corner]/(borderSizes[(corner-1)%4]+borderSizes[corner]))*pi/2
  275.    
  276.     endAngle = (2-corner)%4 * pi/2
  277.     if endAngle == 0:
  278.         endAngle = 2*pi
  279.    
  280.     endAngle -= pi/2   
  281.    
  282.     startAngle = endAngle + absToParam(start,curveDims[(corner+1)%2],curveDims[corner%2])
  283.                                    
  284.     current = startAngle
  285.     previous = current
  286.  
  287.     currentO = endAngle + absToParam(start,oCurveDims[(corner+1)%2],oCurveDims[corner%2])
  288.     previousO = currentO
  289.  
  290.     currentI = endAngle + absToParam(start,iCurveDims[(corner+1)%2],iCurveDims[corner%2])
  291.     previousI = currentI
  292.    
  293.     [R,r] = curveDims if curveDims[0]>curveDims[1] else [curveDims[1],curveDims[0]]
  294.     k = 1- r**2/R**2
  295.     curlen = 0.0
  296.     flag = 0.0
  297.    
  298.     while curlen<dash/2:
  299.         current -= delta*pi/180
  300.         curlen += R*EllipseE(k,current,current+delta*pi/180.0)
  301.    
  302.     if current<=endAngle:
  303.         current=endAngle
  304.         flag=1
  305.            
  306.     currentO = absToParam(paramToAbs(current - endAngle,curveDims[(corner+1)%2],curveDims[corner%2]),oCurveDims[(corner+1)%2],oCurveDims[corner%2]) + endAngle
  307.     currentI = absToParam(paramToAbs(current - endAngle,curveDims[(corner+1)%2],curveDims[corner%2]),iCurveDims[(corner+1)%2],iCurveDims[corner%2]) + endAngle
  308.  
  309.     stepO = (currentO - previousO)/30
  310.     stepI = (currentI - previousI)/30
  311.    
  312.     ctx.move_to(oCurveDims[0]*cos(previousO)/width,oCurveDims[1]*sin(previousO)/height)
  313.  
  314.     for i in range(1,31):
  315.         ctx.line_to(oCurveDims[0]*cos(previousO+stepO*i)/width,oCurveDims[1]*sin(previousO+stepO*i)/height)
  316.    
  317.     ctx.line_to(iCurveDims[0]*cos(currentI)/width,iCurveDims[1]*sin(currentI)/height)
  318.    
  319.     for i in range(1,31):
  320.         ctx.line_to(iCurveDims[0]*cos(currentI-stepI*i)/width,iCurveDims[1]*sin(currentI-stepI*i)/height)
  321.    
  322.     ctx.close_path()
  323.     ctx.fill()
  324.     previous = current
  325.     curlen=0
  326.    
  327.     if flag:
  328.         return
  329.    
  330.     while True:
  331.         while curlen<gap:
  332.             current -= delta*pi/180
  333.             curlen += R*EllipseE(k,current,current+delta*pi/180)
  334.        
  335.         previous = current
  336.         currentO = absToParam(paramToAbs(current - endAngle,curveDims[(corner+1)%2],curveDims[corner%2]),oCurveDims[(corner+1)%2],oCurveDims[corner%2]) + endAngle
  337.         currentI = absToParam(paramToAbs(current - endAngle,curveDims[(corner+1)%2],curveDims[corner%2]),iCurveDims[(corner+1)%2],iCurveDims[corner%2]) + endAngle
  338.         previousO = currentO
  339.         previousI = currentI
  340.         curlen=0
  341.         if current<=endAngle:
  342.             break
  343.                
  344.         while curlen<dash:
  345.             current -= delta*pi/180
  346.             curlen += R*EllipseE(k,current,current+delta*pi/180.0)
  347.        
  348.         if current<endAngle:
  349.             current=endAngle
  350.             flag=1
  351.                
  352.         currentO = absToParam(paramToAbs(current - endAngle,curveDims[(corner+1)%2],curveDims[corner%2]),oCurveDims[(corner+1)%2],oCurveDims[corner%2]) + endAngle
  353.         currentI = absToParam(paramToAbs(current - endAngle,curveDims[(corner+1)%2],curveDims[corner%2]),iCurveDims[(corner+1)%2],iCurveDims[corner%2]) + endAngle
  354.    
  355.         stepO = (currentO - previousO)/30
  356.         stepI = (currentI - previousI)/30
  357.        
  358.         ctx.move_to(oCurveDims[0]*cos(previousO)/width,oCurveDims[1]*sin(previousO)/height)
  359.        
  360.         for i in range(1,31):
  361.             ctx.line_to(oCurveDims[0]*cos(previousO+stepO*i)/width,oCurveDims[1]*sin(previousO+stepO*i)/height)
  362.        
  363.         ctx.line_to(iCurveDims[0]*cos(currentI)/width,iCurveDims[1]*sin(currentI)/height)
  364.        
  365.         for i in range(1,31):
  366.             ctx.line_to(iCurveDims[0]*cos(currentI-stepI*i)/width,iCurveDims[1]*sin(currentI-stepI*i)/height)
  367.        
  368.         ctx.close_path()
  369.         ctx.fill()
  370.         previous = current
  371.         curlen=0
  372.        
  373.         if flag:
  374.             break
  375.            
  376.     ctx.restore()
  377.  
  378. def drawDashedSide(sideIndex):
  379.     """ Draws section of the side with given sideIndex  """
  380.     #Init : Get dashWidth , gapWidth and offset
  381.     raw=calculateDashes(sideIndex)
  382.     dashes=[raw[0]/sides[sideIndex],raw[1]/sides[sideIndex]]
  383.     offset=(raw[2]+raw[0])/sides[sideIndex]
  384.    
  385.     #Draw straight section
  386.     drawStraightSection(sideIndex,dashes,offset)
  387.  
  388.     #Draw left section
  389.     drawCW(sideIndex,raw[0],raw[1])
  390.     #Draw right section
  391.     drawCCW((sideIndex+1)%4,raw[0],raw[1])
  392.    
  393. def initInnerRadii():
  394.     """ Initializes the innerRadii for all corners """
  395.     for i in range(0,4):
  396.         if(i%2==1):
  397.             innerRadii[i][0] = max(borderRadii[i][0]-borderSizes[(i-1)%4],0)
  398.             innerRadii[i][1] = max(borderRadii[i][1]-borderSizes[i],0)
  399.         else:
  400.             innerRadii[i][0] = max(borderRadii[i][0]-borderSizes[i],0)
  401.             innerRadii[i][1] = max(borderRadii[i][1]-borderSizes[(i-1)%4],0)
  402.      
  403. def main():
  404.     initInnerRadii()
  405.     ctx.set_source_rgb (1.0, 0.0, 0.0)
  406.     drawDashedSide(side_top)
  407.     drawDashedSide(side_right)
  408.     drawDashedSide(side_left)
  409.     drawDashedSide(side_bottom)
  410.     surface.write_to_png ("justSides.png")  
  411.  
  412. if __name__ == '__main__':
  413.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement