def __init__(self, north=True, reference_longitude=0, reference_scale=45, celestial=False): """ :param north: whether to plot the north pole :param reference_longitude: the longitude that points to the right :param reference_scale: degrees of latitude per unit distance :param celestial: longitude increases clockwise around north pole """ self.origin = SphericalPoint(0, 0) self._north = north self.reference_longitude = reference_longitude self.reference_scale = reference_scale self._celestial = celestial if self._north: if self.reference_scale >= 90: raise ProjectionError( "Invalid reference scale {} for north pole".format( self.reference_scale)) self.origin_latitude = 90 else: self.reference_scale = -self.reference_scale if self.reference_scale <= -90: raise ProjectionError( "Invalid reference scale {} for south pole".format( self.reference_scale)) self.origin_latitude = -90 self.reverse_polar_direction = not xor(self._north, self._celestial)
def map_meridian(self, longitude): p1 = SphericalPoint(longitude, self.min_latitude) p2 = SphericalPoint(longitude, self.max_latitude) l = self.map_line(Line(p1, p2)) m = self.gridline_factory.meridian(longitude, l) m.border1 = "bottom" m.border2 = "top" m.tickangle1 = 270 m.tickangle2 = 90 return m
def test_projection(self): c = self.p(self.p.parallel_circle_center) self.assertEqual(self.p.cone_angle, 45) f = math.sin(math.radians(self.p.cone_angle)) print f self.assertEqual(self.p(SphericalPoint(0, 45)), Point(0, 0)) self.assertEqual(self.p(SphericalPoint(0, 50)), Point(0, 0.5)) self.assertEqual(self.p(SphericalPoint(0, 35)), Point(0, -1)) #a = 0.98861593*f*15 a = f*15 print a print c p = c + (Point(0, 0) - c).rotate(a)
def map_parallel(self, latitude): p1 = SphericalPoint(self.min_longitude, latitude) p2 = SphericalPoint(self.max_longitude, latitude) l = self.map_line(Line(p1, p2)) if l.p1.x > l.p2.x: l.p1, l.p2 = l.p2, l.p1 p = self.gridline_factory.parallel(latitude, l) p.border1 = "left" p.border2 = "right" p.tickangle1 = 180 p.tickangle2 = 0 return p
def map_meridian(self, longitude, longitude_offsets={}): offset = 0 for l in sorted(longitude_offsets.keys(), reverse=True): if longitude % l == 0: offset = longitude_offsets[l] break if self.projection.reference_latitude > 0: p1 = SphericalPoint(longitude, self.min_latitude) p2 = SphericalPoint(longitude, self.max_latitude - offset) else: p1 = SphericalPoint(longitude, self.min_latitude + offset) p2 = SphericalPoint(longitude, self.max_latitude) l = self.map_line(Line(p1, p2)) if self.bordered: intersections = self.line_intersect_borders(l) if not intersections: return None if len(intersections) == 1: if self.inside_maparea(l.p1): p2, border2 = intersections[0] p1, border1 = l.p1, None else: p1, border1 = intersections[0] p2, border2 = l.p2, None else: p1, border1 = intersections[0] p2, border2 = intersections[1] if p1.y < p2.y: p1, p2 = p2, p1 border1, border2 = border2, border1 l.p1 = p1 l.p2 = p2 else: border1 = "bottom" border2 = "top" m = self.gridline_factory.meridian(longitude, l) m.border1 = border1 m.border2 = border2 m.tickangle1 = l.angle + 180 m.tickangle2 = l.angle if self.gridline_factory.rotate_meridian_labels: m.labelangle1 = l.angle - 90 m.labelangle2 = l.angle - 90 return m
def inverse_project(self, point): if self.celestial: longitude = -self.center_longitude - self.reference_scale * point.x / self.lateral_scale else: longitude = self.center_longitude + self.reference_scale * point.x / self.lateral_scale latitude = point.y * self.reference_scale return SphericalPoint(longitude, latitude)
def map_parallel(self, latitude): c = Circle(SphericalPoint(0, self.projection.origin_latitude), self.projection.origin_latitude - latitude) c = self.map_circle(c) crossings = self.circle_intersect_borders(c) if crossings: parallels = [] for i in range(len(crossings)): a1, c1, b1 = crossings[i - 1] a2, c2, b2 = crossings[i] if a1 > a2: a2 += 360.0 aavg = math.radians(0.5 * (a1 + a2)) pavg = c.center + Point(c.radius * math.cos(aavg), c.radius * math.sin(aavg)) if self.inside_maparea(pavg): arc = Arc(c.center, c.radius, a1, a2) p = self.gridline_factory.parallel(latitude, arc) parallels.append(p) else: p = self.gridline_factory.parallel(latitude, c) parallels = [p] return parallels
def test_latitude(self): self.assertEqual(self.p.project(SphericalPoint(0, 50)), Point(1, 0)) self.assertEqual(self.p.project(SphericalPoint(90, 50)), Point(0, 1)) self.assertEqual(self.p.project(SphericalPoint(180, 50)), Point(-1, 0)) self.assertEqual(self.p.project(SphericalPoint(270, 50)), Point(0, -1)) self.p.celestial = True self.assertEqual(self.p.project(SphericalPoint(0, 50)), Point(1, 0)) self.assertEqual(self.p.project(SphericalPoint(90, 50)), Point(0, -1)) self.assertEqual(self.p.project(SphericalPoint(180, 50)), Point(-1, 0)) self.assertEqual(self.p.project(SphericalPoint(270, 50)), Point(0, 1))
def map_meridian(self, longitude, longitude_offsets={}): """Returns the exact line to draw for a meridian""" offset = 0 for l in sorted(longitude_offsets.keys(), reverse=True): if longitude % l == 0: offset = longitude_offsets[l] break if self.projection.north: p1 = SphericalPoint(longitude, self.projection.origin_latitude - offset) else: p1 = SphericalPoint(longitude, self.projection.origin_latitude + offset) if self.projection.north: p2 = SphericalPoint(longitude, self.min_latitude) else: p2 = SphericalPoint(longitude, self.max_latitude) l = self.map_line(Line(p1, p2)) if self.bordered: p2, border2 = self.line_intersect_borders(l)[0] l.p2 = p2 else: border2 = "bottom" m = self.gridline_factory.meridian(longitude, l) m.border2 = border2 if xor(self.projection.north, not self.projection.celestial): m.tickangle2 = -longitude + self.projection.reference_longitude else: m.tickangle2 = longitude - self.projection.reference_longitude if self.gridline_factory.rotate_meridian_labels: m.labelpos2 = 270 m.labelangle2 = l.angle + 90 else: pass return m
def get_constellation_boundaries_for_area(min_longitude, max_longitude, min_latitude, max_latitude, epoch=REFERENCE_EPOCH): # Convert longitude to 0-360 values # TODO: sometimes boundaries cross the map but have no vertices within the map area + margin and are not plotted min_longitude = ensure_angle_range(min_longitude) max_longitude = ensure_angle_range(max_longitude) if max_longitude == min_longitude: max_longitude += 360 db = SkyMapDatabase() q = "SELECT * FROM skymap_constellation_boundaries WHERE" if min_longitude < max_longitude: q += " ((ra1>={0} AND ra1<={1}".format(min_longitude, max_longitude) else: q += " (((ra1>={0} OR ra1<={1})".format(min_longitude, max_longitude) q += " AND dec1>={0} AND dec1<={1}) OR".format(min_latitude, max_latitude) if min_longitude < max_longitude: q += " (ra2>={0} AND ra2<={1}".format(min_longitude, max_longitude) else: q += " ((ra2>={0} OR ra2<={1})".format(min_longitude, max_longitude) q += " AND dec2>={0} AND dec2<={1}))".format(min_latitude, max_latitude) res = db.query(q) result = [] pc = PrecessionCalculator(CONST_BOUND_EPOCH, epoch) for row in res: p1 = SphericalPoint(row['ra1'], row['dec1']) p2 = SphericalPoint(row['ra2'], row['dec2']) e = BoundaryEdge(p1, p2) e.precess(pc) result.append(e) db.close() return result
def inverse_project(self, point): rho = self.origin.distance(point) theta = ensure_angle_range(math.degrees(math.atan2(point.y, point.x))) if self.reverse_polar_direction: longitude = ensure_angle_range(-theta + self.reference_longitude) else: longitude = ensure_angle_range(theta + self.reference_longitude) return SphericalPoint( longitude, -rho * self.reference_scale + self.origin_latitude)
def get_milky_way_curve(id): db = SkyMapDatabase() q = "SELECT * FROM milkyway WHERE curve_id={0} ORDER BY id ASC".format(id) result = db.query(q) curve = [] for row in result: curve.append(SphericalPoint(row['ra'], row['dec'])) if curve[0] == curve[-1]: curve = curve[:-1] db.close() return curve
def test_inverse_project(self): self.assertEqual(self.p.inverse_project(Point(1, 0)), SphericalPoint(0, 50)) self.assertEqual(self.p.inverse_project(Point(0, 1)), SphericalPoint(90, 50)) self.assertEqual(self.p.inverse_project(Point(-1, 0)), SphericalPoint(180, 50)) self.assertEqual(self.p.inverse_project(Point(0, -1)), SphericalPoint(270, 50)) p = SphericalPoint(225, 76) pp = self.p.project(p) ppp = self.p.inverse_project(pp) self.assertEqual(p, ppp) self.p.celestial = True self.assertEqual(self.p.inverse_project(Point(1, 0)), SphericalPoint(0, 50)) self.assertEqual(self.p.inverse_project(Point(0, 1)), SphericalPoint(270, 50)) self.assertEqual(self.p.inverse_project(Point(-1, 0)), SphericalPoint(180, 50)) self.assertEqual(self.p.inverse_project(Point(0, -1)), SphericalPoint(90, 50)) p = SphericalPoint(225, 76) pp = self.p.project(p) ppp = self.p.inverse_project(pp) self.assertEqual(p, ppp)
def inverse_project(self, point): rho = self.reference_scale * numpy.sign( self.n) * math.sqrt(point.x**2 + (self.rho_0 - point.y)**2) theta = math.degrees(math.atan2(point.x, self.rho_0 - point.y)) if self.celestial: longitude = self.reference_longitude - theta / self.n else: longitude = self.reference_longitude + theta / self.n latitude = math.degrees(self.G - rho) return SphericalPoint(longitude, latitude)
def precess(self, pc): if not self.interpolated_points: self.interpolated_points = self.interpolate_points() precessed_points = [] for p in self.interpolated_points: pra, pdec = pc.precess(p.ra, p.dec) precessed_points.append(SphericalPoint(pra, pdec)) self.epoch = pc.epoch2 self.p1 = precessed_points[0] self.p2 = precessed_points[-1] self.interpolated_points = precessed_points
def draw_internal_parallel_ticks(self, longitude, angle=90, labels=False, label_angle=None): reference_meridian = self.map_meridian(longitude) tickangle = reference_meridian.meridian.angle + angle start_latitude = self.gridline_factory.parallel_tick_interval * math.ceil( self.min_latitude / self.gridline_factory.parallel_tick_interval) for latitude in numpy.arange( start_latitude, self.max_latitude, self.gridline_factory.parallel_tick_interval): if latitude in [-90, 90]: continue p1 = self.projection(SphericalPoint(longitude, latitude)) if not self.inside_maparea(p1): continue delta = Point(1, 0).rotate(tickangle) if latitude % self.gridline_factory.parallel_line_interval == 0: ticksize = 0 elif latitude % self.gridline_factory.parallel_marked_tick_interval == 0: ticksize = self.gridline_factory.marked_ticksize else: ticksize = self.gridline_factory.unmarked_ticksize if ticksize > 0: p2 = p1 + ticksize * delta self.draw_line( Line(p1, p2), linewidth=self.gridline_factory.gridline_thickness) if labels and latitude % self.gridline_factory.parallel_line_interval == 0: p3 = p1 + 0.75 * delta text = "{}\\textdegree".format(int(abs(latitude))) if abs < 0: text = "--" + text else: text = "+" + text if label_angle is None: label_angle = tickangle l = Label(p3, text, label_angle, "tiny", angle=0, fill="white") self.draw_label(l)
def extract_point(line): point_pattern = "^[A-Z]+\s(\d\d \d\d \d\d), (\-?)(\d\d \d\d)$" m = re.search(point_pattern, line) try: long = m.groups()[0] latsign = m.groups()[1] lat = m.groups()[2] if latsign == "-": latsign = -1 else: latsign = 1 h, m, s = (int(x) for x in long.split()) longitude = HourAngle(h, m, s).to_degrees() d, m = (int(x) for x in lat.split()) latitude = DMSAngle(degrees=d, minutes=m, sign=latsign).to_degrees() return SphericalPoint(longitude, latitude) except AttributeError: return None
def __init__(self, center, standard_parallel1, standard_parallel2, reference_scale=50, celestial=False): self.celestial = celestial self.reference_longitude = center[0] self.reference_latitude = center[1] self.standard_parallel1 = standard_parallel1 self.standard_parallel2 = standard_parallel2 self.reference_scale = abs(math.radians(reference_scale)) self.cone_angle = 90 - 0.5 * abs(self.standard_parallel1 + self.standard_parallel2) # Calculate projection parameters phi_1 = math.radians(self.standard_parallel1) phi_2 = math.radians(self.standard_parallel2) self.n = (math.cos(phi_1) - math.cos(phi_2)) / (phi_2 - phi_1) self.G = math.cos(phi_1) / self.n + phi_1 self.rho_0 = (self.G - math.radians( self.reference_latitude)) / self.reference_scale self.parallel_circle_center = SphericalPoint(0, math.degrees(self.G))
def test_inverse_projection(self): self.assertEqual(self.p(Point(0, 0), inverse=True), SphericalPoint(0, 45)) self.assertEqual(self.p(self.p(SphericalPoint(15, 45)), inverse=True), SphericalPoint(15, 45)) self.assertEqual(self.p(self.p(SphericalPoint(-15, 45)), inverse=True), SphericalPoint(-15, 45)) self.assertEqual(self.p(self.p(SphericalPoint(29, 32)), inverse=True), SphericalPoint(29, 32)) self.p.celestial = True self.assertEqual(self.p(Point(0, 0), inverse=True), SphericalPoint(0, 45)) self.assertEqual(self.p(self.p(SphericalPoint(15, 45)), inverse=True), SphericalPoint(15, 45)) self.assertEqual(self.p(self.p(SphericalPoint(-15, 45)), inverse=True), SphericalPoint(-15, 45)) self.assertEqual(self.p(self.p(SphericalPoint(29, 32)), inverse=True), SphericalPoint(29, 32))
def test_latitude(self): self.assertEqual(self.p.project(SphericalPoint(0, 30)), Point(0, 1)) self.assertEqual(self.p.project(SphericalPoint(0, -30)), Point(0, -1))
def test_longitude(self): self.assertEqual(self.p.project(SphericalPoint(0, 0)), Point(0, 0)) self.assertEqual(self.p.project(SphericalPoint(30, 0)), Point(1, 0)) self.assertEqual(self.p.project(SphericalPoint(-30, 0)), Point(-1, 0))
def test_other_scale(self): self.p = AzimuthalEquidistantProjection(reference_longitude=0, reference_scale=80.0/190.0) self.assertEqual(self.p.project(SphericalPoint(0, 50)), Point(95, 0))
def test_pole(self): self.assertEqual(self.p.project(SphericalPoint(0, 90)), self.origin)
def test_reference_longitude(self): self.p.reference_longitude = 40 self.assertEqual(self.origin.distance(self.p.project(SphericalPoint(0, 50))), 1.0) self.assertEqual(self.p.project(SphericalPoint(40, 50)), Point(1, 0)) self.assertEqual(self.p.project(SphericalPoint(130, 50)), Point(0, 1)) self.assertEqual(self.p.project(SphericalPoint(220, 50)), Point(-1, 0)) self.assertEqual(self.p.project(SphericalPoint(310, 50)), Point(0, -1)) p = SphericalPoint(225, 76) pp = self.p.project(p) ppp = self.p.inverse_project(pp) self.assertEqual(p, ppp) self.p.celestial = True self.assertEqual(self.p.project(SphericalPoint(40, 50)), Point(1, 0)) self.assertEqual(self.p.project(SphericalPoint(130, 50)), Point(0, -1)) self.assertEqual(self.p.project(SphericalPoint(220, 50)), Point(-1, 0)) self.assertEqual(self.p.project(SphericalPoint(310, 50)), Point(0, 1)) p = SphericalPoint(225, 76) pp = self.p.project(p) ppp = self.p.inverse_project(pp) self.assertEqual(p, ppp) self.p.celestial = False self.p.reference_longitude = -40 self.assertEqual(self.p.project(SphericalPoint(-40, 50)), Point(1, 0)) self.assertEqual(self.p.project(SphericalPoint(50, 50)), Point(0, 1)) self.assertEqual(self.p.project(SphericalPoint(140, 50)), Point(-1, 0)) self.assertEqual(self.p.project(SphericalPoint(230, 50)), Point(0, -1))
def azimuthal_map(chart_number, chart_side, north, delta=None): offset = 23 latitude_range = 12 if north: reference_longitude = 270 else: reference_longitude = 90 if delta is not None: origin_x = 5 * MM_PER_DEGREE + delta else: origin_x = 5 * MM_PER_DEGREE if chart_side == 'left': fn = "{:02}A".format(chart_number) f = leftfigure(fn) map_llcorner = LMAP_LLCORNER + Point(7, LEGEND_HEIGHT + offset) map_urcorner = map_llcorner + Point(10 * MM_PER_DEGREE, latitude_range * MM_PER_DEGREE) map_origin = map_llcorner + Point(origin_x, 0.5 * latitude_range * MM_PER_DEGREE) else: fn = "{:02}B".format(chart_number) f = rightfigure(fn) map_lrcorner = RMAP_LLCORNER + Point(LEGEND_WIDTH - 7, 0) + Point( 0, LEGEND_HEIGHT + offset) map_llcorner = map_lrcorner + Point(-10 * MM_PER_DEGREE, 0) map_urcorner = map_lrcorner + Point(0, latitude_range * MM_PER_DEGREE) map_origin = map_lrcorner + Point(-origin_x, 0.5 * latitude_range * MM_PER_DEGREE) m = AzimuthalEquidistantMapArea(map_llcorner, map_urcorner, hmargin=MAP_HMARGIN, vmargin=MAP_VMARGIN, origin=map_origin, north=north, reference_longitude=reference_longitude, latitude_range=latitude_range, celestial=True, box=False) if delta is None: if chart_side == "left": if north: p1 = m.projection(SphericalPoint(90, 84)) else: p1 = m.projection(SphericalPoint(270, -84)) delta = map_llcorner.x - (map_origin.x + p1.x) else: if north: p1 = m.projection(SphericalPoint(270, 84)) else: p1 = m.projection(SphericalPoint(90, -84)) delta = -(map_lrcorner.x - (map_origin.x + p1.x)) return azimuthal_map(chart_number, chart_side, north, delta) f.add(m) m.bordered = False m.gridline_factory.meridian_line_interval = 15 m.gridline_factory.meridian_marked_tick_interval = 15 m.gridline_factory.meridian_tick_interval = 15 m.gridline_factory.parallel_line_interval = 1 m.gridline_factory.parallel_marked_tick_interval = 1 m.gridline_factory.parallel_tick_interval = 1 m.gridline_factory.marked_ticksize = 0 m.gridline_factory.unmarked_ticksize = 0 m.gridline_factory.fixed_tick_reach = False m.gridline_factory.label_distance = 1 m.gridline_factory.rotate_meridian_labels = True m.gridline_factory.meridian_labeltextfunc = azimuthal_meridian_label m.gridline_factory.rotate_poles = True m.gridline_factory.pole_marker_size = 1 m.min_longitude = 0 m.max_longitude = 360 if north: m.min_latitude = 84 m.max_latitude = 90 else: m.min_latitude = -90 m.max_latitude = -84 return f, m
def draw_coordinate_system(self, transformation, linewidth=0.3, dashed='dashed', tickinterval=None, poles=False): points = [] for longitude in numpy.arange(0, 360.1, 0.251): p = transformation(SphericalPoint(longitude, 0)) points.append( SphericalPoint(self.projection.reduce_longitude(p.longitude), p.latitude)) points_to_draw = [] for i in range(len(points)): prev_p = points[i - 1] p = points[i] if i + 1 == len(points): next_p = points[0] else: next_p = points[i + 1] if self.bordered: prev_p = self.map_point(prev_p) p = self.map_point(p) next_p = self.map_point(next_p) if self.inside_maparea(prev_p) or self.inside_maparea( p) or self.inside_maparea(next_p): points_to_draw.append(p) else: prevpinside = self.inside_coordinate_range(prev_p) pinside = self.inside_coordinate_range(p) nextpinside = self.inside_coordinate_range(next_p) if prevpinside or pinside or nextpinside: points_to_draw.append(self.map_point(p)) points_to_draw = sorted(points_to_draw, key=attrgetter('x')) if points_to_draw: self.draw_polygon(points_to_draw, linewidth=linewidth, dashed=dashed) # Ticks if tickinterval is not None: for i in range(360 / int(tickinterval)): l = i * tickinterval p = transformation(SphericalPoint(l, 0)) p.longitude = self.projection.reduce_longitude(p.longitude) if self.bordered: p = self.map_point(p) if not self.inside_maparea(p): continue else: if not self.inside_coordinate_range(p): continue p = self.map_point(p) v = self.map_point(transformation(SphericalPoint(l + 1, 0))) - p v = v.rotate(90) / v.norm tp1 = p + 0.5 * v tp2 = p - 0.5 * v lp = p + 0.8 * v tick = Line(tp1, tp2) self.draw_line(tick, linewidth=linewidth) self.draw_label( Label(lp, "\\textit{{{}\\textdegree}}".format(l), 270, "miniscule", angle=tick.angle - 90, fill="white")) # Poles if poles: p = transformation(SphericalPoint(0, 90)) np = self.map_point(p) if self.gridline_factory.rotate_poles: delta1 = self.map_point(p + SphericalPoint(1, 0)) - np delta2 = self.map_point(p + SphericalPoint(0, 1)) - np else: delta1 = Point(1, 0) delta2 = Point(0, 1) delta1 *= self.gridline_factory.pole_marker_size / delta1.norm delta2 *= self.gridline_factory.pole_marker_size / delta2.norm if self.inside_maparea(np): bl1 = Line(np + 1.25 * delta1, np - 1.25 * delta1) l1 = Line(np + delta1, np - delta1) bl2 = Line(np + 1.25 * delta2, np - 1.25 * delta2) l2 = Line(np + delta2, np - delta2) self.draw_line(bl1, linewidth=3 * linewidth, color="white") self.draw_line(bl2, linewidth=3 * linewidth, color="white") self.draw_line( l1, linewidth=self.gridline_factory.gridline_thickness) self.draw_line( l2, linewidth=self.gridline_factory.gridline_thickness) p = transformation(SphericalPoint(0, -90)) sp = self.map_point(p) if self.gridline_factory.rotate_poles: delta1 = self.map_point(p + SphericalPoint(1, 0)) - sp delta2 = self.map_point(p + SphericalPoint(0, 1)) - sp else: delta1 = Point(1, 0) delta2 = Point(0, 1) delta1 *= self.gridline_factory.pole_marker_size / delta1.norm delta2 *= self.gridline_factory.pole_marker_size / delta2.norm if self.inside_maparea(sp): bl1 = Line(sp + 1.25 * delta1, sp - 1.25 * delta1) l1 = Line(sp + delta1, sp - delta1) bl2 = Line(sp + 1.25 * delta2, sp - 1.25 * delta2) l2 = Line(sp + delta2, sp - delta2) self.draw_line(bl1, linewidth=3 * linewidth, color="white") self.draw_line(bl2, linewidth=3 * linewidth, color="white") self.draw_line( l1, linewidth=self.gridline_factory.gridline_thickness) self.draw_line( l2, linewidth=self.gridline_factory.gridline_thickness)
def test_south_pole(self): self.p = AzimuthalEquidistantProjection(north=False, reference_longitude=0, reference_scale=40) # Pole self.assertEqual(self.p.project(SphericalPoint(0, -90)), self.origin) # Project self.assertEqual(self.p.project(SphericalPoint(0, -50)), Point(1, 0)) self.assertEqual(self.p.project(SphericalPoint(90, -50)), Point(0, -1)) self.assertEqual(self.p.project(SphericalPoint(180, -50)), Point(-1, 0)) self.assertEqual(self.p.project(SphericalPoint(270, -50)), Point(0, 1)) self.p.celestial = True self.assertEqual(self.p.project(SphericalPoint(0, -50)), Point(1, 0)) self.assertEqual(self.p.project(SphericalPoint(90, -50)), Point(0, 1)) self.assertEqual(self.p.project(SphericalPoint(180, -50)), Point(-1, 0)) self.assertEqual(self.p.project(SphericalPoint(270, -50)), Point(0, -1)) # Inverse project self.p.celestial = False self.assertEqual(self.p.inverse_project(Point(1, 0)), SphericalPoint(0, -50)) self.assertEqual(self.p.inverse_project(Point(0, -1)), SphericalPoint(90, -50)) self.assertEqual(self.p.inverse_project(Point(-1, 0)), SphericalPoint(180, -50)) self.assertEqual(self.p.inverse_project(Point(0, 1)), SphericalPoint(270, -50)) p = SphericalPoint(225, -76) pp = self.p.project(p) ppp = self.p.inverse_project(pp) self.assertEqual(p, ppp) self.p.celestial = True self.assertEqual(self.p.inverse_project(Point(1, 0)), SphericalPoint(0, -50)) self.assertEqual(self.p.inverse_project(Point(0, 1)), SphericalPoint(90, -50)) self.assertEqual(self.p.inverse_project(Point(-1, 0)), SphericalPoint(180, -50)) self.assertEqual(self.p.inverse_project(Point(0, -1)), SphericalPoint(270, -50)) p = SphericalPoint(225, -76) pp = self.p.project(p) ppp = self.p.inverse_project(pp) self.assertEqual(p, ppp)
def position(self): """Returns the position of the star in degrees""" return SphericalPoint(self.right_ascension, self.declination)
def conic_map(chart_number, chart_side, min_longitude, max_longitude, min_latitude, max_latitude, meridian_interval, offset, delta=None): latitude_range = max_latitude - min_latitude center_latitude = min_latitude + 0.5 * latitude_range if delta is not None: offset += delta if chart_side == 'left': fn = "{:02}A".format(chart_number) f = leftfigure(fn) map_llcorner = LMAP_LLCORNER + Point(0, LEGEND_HEIGHT + offset) map_urcorner = map_llcorner + Point(LEGEND_WIDTH, latitude_range * MM_PER_DEGREE) center_longitude = min_longitude map_origin = map_llcorner + Point(LEGEND_WIDTH, 0.5 * latitude_range * MM_PER_DEGREE) else: fn = "{:02}B".format(chart_number) f = rightfigure(fn) map_llcorner = RMAP_LLCORNER + Point(0, LEGEND_HEIGHT + offset) map_urcorner = map_llcorner + Point(LEGEND_WIDTH, latitude_range * MM_PER_DEGREE) center_longitude = max_longitude map_origin = map_llcorner + Point(0, 0.5 * latitude_range * MM_PER_DEGREE) sp1 = min_latitude + int(round(latitude_range / 6.0)) sp2 = min_latitude + int(round(5.0 * latitude_range / 6.0)) m = EquidistantConicMapArea(map_llcorner, map_urcorner, hmargin=MAP_HMARGIN, vmargin=MAP_VMARGIN, center=(center_longitude, center_latitude), standard_parallel1=sp1, standard_parallel2=sp2, latitude_range=latitude_range, origin=map_origin, celestial=True, box=False) # Determine correct origin for south conic maps if center_latitude < 0 and delta is None: p1 = m.projection(SphericalPoint(max_longitude, min_latitude)) p2 = m.projection(SphericalPoint(min_longitude, min_latitude)) delta = abs(p1.y - p2.y) return conic_map(chart_number, chart_side, min_longitude, max_longitude, min_latitude, max_latitude, meridian_interval, offset, delta) f.add(m) m.bordered = False m.gridline_factory.meridian_line_interval = meridian_interval m.gridline_factory.meridian_marked_tick_interval = meridian_interval m.gridline_factory.meridian_tick_interval = meridian_interval m.gridline_factory.parallel_line_interval = 1 m.gridline_factory.parallel_marked_tick_interval = 1 m.gridline_factory.parallel_tick_interval = 1 m.gridline_factory.marked_ticksize = 0 m.gridline_factory.unmarked_ticksize = 0 m.gridline_factory.fixed_tick_reach = False m.gridline_factory.label_distance = 1 m.gridline_factory.rotate_parallel_labels = True m.gridline_factory.rotate_meridian_labels = True m.gridline_factory.meridian_labeltextfunc = meridian_label m.gridline_factory.rotate_poles = True m.gridline_factory.pole_marker_size = 1 m.min_longitude = min_longitude m.max_longitude = max_longitude m.min_latitude = min_latitude m.max_latitude = max_latitude return f, m
def map_parallel(self, latitude): p = SphericalPoint(0, latitude) radius = p.distance(self.projection.parallel_circle_center) center = self.projection.parallel_circle_center c = Circle(center, radius) c = self.map_circle(c) if self.bordered: crossings = self.circle_intersect_borders(c) if crossings: parallels = [] for i in range(len(crossings)): a1, c1, b1 = crossings[i - 1] a2, c2, b2 = crossings[i] if a1 > a2: a2 += 360.0 aavg = math.radians(0.5 * (a1 + a2)) pavg = c.center + Point(c.radius * math.cos(aavg), c.radius * math.sin(aavg)) if self.inside_maparea(pavg): arc = Arc(c.center, c.radius, a1, a2) p = self.gridline_factory.parallel(latitude, arc) p.border1 = b1 p.tickangle1 = a1 + 90 if self.gridline_factory.rotate_parallel_labels: if latitude > 0: p.labelangle1 = a1 + 90 else: p.labelangle1 = a1 - 90 else: p.labelangle1 = 0 p.border2 = b2 p.tickangle2 = a2 + 90 if self.gridline_factory.rotate_parallel_labels: if latitude > 0: p.labelangle2 = a2 + 90 else: p.labelangle2 = a2 - 90 else: p.labelangle2 = 0 parallels.append(p) else: if self.inside_maparea(c.center): p = self.gridline_factory.parallel(latitude, c) parallels = [p] else: parallels = [] else: if self.projection.reference_latitude > 0: start_angle = self.map_meridian( self.min_longitude).meridian.angle + 180 stop_angle = self.map_meridian( self.max_longitude).meridian.angle + 180 else: start_angle = self.map_meridian( self.max_longitude).meridian.angle stop_angle = self.map_meridian( self.min_longitude).meridian.angle a = Arc(c.center, c.radius, start_angle, stop_angle) p = self.gridline_factory.parallel(latitude, a) if self.projection.reference_latitude > 0: p.border1 = 'right' else: p.border1 = 'left' p.tickangle1 = start_angle + 90 if self.gridline_factory.rotate_parallel_labels: if self.projection.reference_latitude > 0: p.labelangle1 = start_angle + 90 else: p.labelangle1 = start_angle - 90 else: p.labelangle1 = 0 if self.projection.reference_latitude > 0: p.border2 = 'left' else: p.border2 = 'right' p.tickangle2 = stop_angle - 90 if self.gridline_factory.rotate_parallel_labels: if self.projection.reference_latitude > 0: p.labelangle2 = stop_angle + 90 else: p.labelangle2 = stop_angle - 90 else: p.labelangle2 = 0 parallels = [p] return parallels