#
# $Id: hammer.py,v 1.25 2001/10/29 07:52:53 mrnolta Exp $
#
# Copyright (C) 2000-2001 :
#
# Walter Brisken <walterfb@users.sourceforge.net>
# Mike Nolta <mrnolta@users.sourceforge.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#
#
# Hammer-Aitoff coordinates are an equal area projection of the
# sphere into the plane. The spherical coordinates l and b are
# used where l runs from -pi to pi and b from -pi/2 to pi/2.
# The equator is b=0, and b = +/-pi/2 are the north/south poles.
#
import math
from biggles import \
_series, _PlotComposite, _PlotGeometry, _PlotContainer, Geodesic, Curve
from geometry import *
import _biggles
class _HammerAitoffGeometry:
def __init__( self, dest, l0=0., b0=0, rot=0. ):
self.src_bbox = BoundingBox( (-1.,-.5), (1.,.5) )
self.dest_bbox = dest
self.aff = RectilinearMap( self.src_bbox, dest )
self.l0 = l0
self.b0 = b0
self.rot = rot
def __call__( self, l_, b_ ):
xh, yh = _biggles.hammer_call( \
l_, b_, self.l0, self.b0, self.rot )
return self.aff( xh, yh )
def call_vec( self, l_, b_ ):
xh, yh = _biggles.hammer_call_vec( \
l_, b_, self.l0, self.b0, self.rot )
return self.aff.call_vec( xh, yh )
def geodesic( self, l_, b_, div=2 ):
l, b = _biggles.hammer_geodesic_fill( l_, b_, div )
segs = []
i0 = 0
for i in range(1,len(l)):
if _biggles.hammer_connect( \
l[i-1], b[i-1], l[i], b[i], \
self.l0, self.b0, self.rot ):
segs.append( (l[i0:i],b[i0:i]) )
i0 = i
segs.append( (l[i0:],b[i0:]) )
return segs
class _HammerAitoffContext:
def __init__( self, device, dev, l0=0., b0=0., rot=0. ):
self.draw = device
self.dev_bbox = dev
self.geom = _HammerAitoffGeometry( dev, l0, b0, rot )
self.plot_geom = _PlotGeometry( BoundingBox((0,0),(1,1)), dev )
def do_clip( self ):
pass
class HammerAitoffPlot( _PlotContainer ):
_attr_deprecated = {
"num_l_ribs" : "ribs_l",
"num_b_ribs" : "ribs_b",
}
def __init__( self, l0=0., b0=0, rot=0., **kw ):
apply( _PlotContainer.__init__, (self,) )
apply( self.conf_setattr, ("HammerAitoffPlot",), kw )
self.content = _PlotComposite()
self.l0 = l0
self.b0 = b0
self.rot = rot
_attr_deprecated = {
"num_l_ribs" : "ribs_l",
"num_b_ribs" : "ribs_b",
}
def __setattr__( self, name, value ):
self.__dict__[ self._attr_deprecated.get(name,name) ] = value
def __iadd__( self, other ):
self.add( other )
def add( self, *args ):
apply( self.content.add, args )
def _draw_background( self, context ):
pc = _PlotComposite()
nl = self.ribs_l
b = _series( -90/2, 90/2, 2*math.pi/180. )
for l0 in _series( -nl, nl, math.pi/nl ):
c = apply( Curve, ([l0]*len(b), b), self.ribs_style )
pc.add( c )
nb = self.ribs_b
l = _series( -180/2, 180/2, 2*math.pi/180. )
for b0 in _series( -nb, nb, 0.5*math.pi/(nb+1) ):
c = apply( Curve, (l, [b0]*len(l)), self.ribs_style )
pc.add( c )
pc.render( context )
def exterior( self, device, interior ):
bb = interior.copy()
context = _HammerAitoffContext( device, interior,
self.l0, self.b0, self.rot )
bb.union( self.content.bbox(context) )
return bb
def compose_interior( self, device, interior ):
_PlotContainer.compose_interior( self, device, interior )
context = _HammerAitoffContext( device, interior,
self.l0, self.b0, self.rot )
self._draw_background( context )
self.content.render( context )
|