def testClock(self): # Create a new clock (inside a document packet) doc = czml.CZMLPacket(id='document', version='1.0') c = czml.Clock() c.currentTime = '2017-08-21T16:50:00Z' c.multiplier = 3 c.range = 'UNBOUNDED' c.step = 'SYSTEM_CLOCK_MULTIPLIER' self.assertEqual( c.data(), { 'currentTime': '2017-08-21T16:50:00Z', 'multiplier': 3, 'range': 'UNBOUNDED', 'step': 'SYSTEM_CLOCK_MULTIPLIER' }) doc.clock = c self.assertEqual( doc.data(), { 'id': 'document', 'version': '1.0', 'clock': { 'currentTime': '2017-08-21T16:50:00Z', 'multiplier': 3, 'range': 'UNBOUNDED', 'step': 'SYSTEM_CLOCK_MULTIPLIER' }, }) # Test that clock can only be added to the document object (id='document') doc = czml.CZMLPacket(id='foo') c = czml.Clock() self.assertRaises(Exception, setattr, doc, 'clock', c)
def testLabel(self): # Create a new label l = czml.Label() l.text = 'test label' l.show = False self.assertEqual(l.data(), {'text': 'test label', 'show': False}) # Modify an existing label l.show = True self.assertEqual(l.data(), {'text': 'test label', 'show': True}) # Create a new label from an existing label l2 = czml.Label() l2.loads(l.dumps()) self.assertEqual(l.data(), l2.data()) # Add a label toa CZML packet packet = czml.CZMLPacket(id='abc') packet.label = l2 self.assertEqual(packet.data(), { 'id': 'abc', 'label': { 'text': 'test label', 'show': True }, })
def testDocument(self): # Create a new document packet doc_packet1 = czml.CZMLPacket(id='document', version='1.0') self.assertEqual(doc_packet1.data(), { 'id': 'document', 'version': '1.0' }) # Modify an existing document packet doc_packet1.version = '1.1' self.assertEqual(doc_packet1.data(), { 'id': 'document', 'version': '1.1' }) # Create a new document packet from an existing document packet doc_packet2 = czml.CZMLPacket() doc_packet2.loads(doc_packet1.dumps()) self.assertEqual(doc_packet1.data(), doc_packet2.data()) # Test that version can only be added to the document packet (id='document') with self.assertRaises(Exception): doc_packet1 = czml.CZMLPacket(id='foo', version='1.0') doc_packet1 = czml.CZMLPacket(id='foo') self.assertRaises(Exception, setattr, doc_packet1, 'version', '1.0') # Test the writing of CZML using the write() method and the reading of that CZML using the loads() method doc = czml.CZML() doc.packets.append(doc_packet2) label_packet = czml.CZMLPacket(id='label') label = czml.Label() label.text = 'test label' label.show = True label_packet.label = label doc.packets.append(label_packet) test_filename = 'test.czml' doc.write(test_filename) with open(test_filename, 'r') as test_file: doc2 = czml.CZML() doc2.loads(test_file.read()) self.assertEqual(doc.dumps(), doc2.dumps()) os.remove(test_filename)
def __init__(self, verbose=False): """Construct a CZMLWriter. Args: verbose (bool): Extra messaging from methods. """ self.doc = czml.CZML() self.doc.packets.append(czml.CZMLPacket(id="document", version="1.0")) self.timestep_count = 0 self.sim_end_date = None self.sim_start_date = None self._verbose = verbose
def create(ICAO, longitude, latitude, height): packet2 = czml.CZMLPacket(id=ICAO) lb = czml.Label(text=ICAO, show=True) lb.scale = 0.5 lb.pixelOffset = {'cartesian2': [30, -20]} packet2.label = lb packet2.position = {"cartographicDegrees": [longitude, latitude, height]} md = czml.Model() md.gltf = "../../Models/b737.glb" md.maximumScale = 20000 md.minimumPixelSize = 64 packet2.model = md doc.packets.append(packet2)
def testBillboard(self): # Create a new billboard bb = czml.Billboard(show=True, scale=0.7) bb.image = 'http://localhost/img.png' bb.color = {'rgba': [0, 255, 127, 55]} self.assertEqual( bb.data(), { 'image': 'http://localhost/img.png', 'scale': 0.7, 'color': { 'rgba': [0, 255, 127, 55] }, 'show': True }) # Modify an existing billboard bb.image = 'http://localhost/img2.png' bb.scale = 1.3 bb.color = {'rgba': [127, 0, 255, 160]} bb.show = False self.assertEqual( bb.data(), { 'image': 'http://localhost/img2.png', 'scale': 1.3, 'color': { 'rgba': [127, 0, 255, 160] }, 'show': False }) # Create a new billboard from an existing billboard bb2 = czml.Billboard() bb2.loads(bb.dumps()) self.assertEqual(bb.data(), bb2.data()) # Add a billboard to a CZML packet packet = czml.CZMLPacket(id='abc') packet.billboard = bb2 self.assertEqual( packet.data(), { 'id': 'abc', 'billboard': { 'image': 'http://localhost/img2.png', 'scale': 1.3, 'color': { 'rgba': [127, 0, 255, 160] }, 'show': False }, })
def testDescription(self): packet = czml.CZMLPacket(id='the_id') packet.description = '<h1>Hello World</h1>' self.assertEqual(packet.data(), { 'id': 'the_id', 'description': '<h1>Hello World</h1>' }) # Add a description as a dict packet.description = 'As a dict' self.assertEqual(packet.data(), { 'id': 'the_id', 'description': 'As a dict' })
def create(obj_id, longitude, latitude, height): packet2 = czml.CZMLPacket(id=obj_id) packet2.name = "BEIDOU1" lb = czml.Label(text="北斗卫星", show=True) lb.scale = 0.5 lb.pixelOffset = {'cartesian2': [50, -30]} packet2.label = lb packet2.position = {"cartographicDegrees": [longitude, latitude, height]} md = czml.Model() md.gltf = "../../Models/a2100.gltf" md.maximumScale = 20000 md.minimumPixelSize = 64 packet2.model = md doc.packets.append(packet2)
def testDescription(self): # Create a new description d = czml.Description(string='<h1>Hello World</h1>', reference='the reference') self.assertEqual(d.data(), { 'string': '<h1>Hello World</h1>', 'reference': 'the reference' }) # Create a new description from an existing description d2 = czml.Description() d2.loads(d.dumps()) self.assertEqual(d2.data(), d.data()) # Change an existing description d.string = '<h1>Hello World Again</h1>' print(d) self.assertEqual(d.data(), { 'string': '<h1>Hello World Again</h1>', 'reference': 'the reference' }) # Verfy passing unkown value with self.assertRaises(Exception): d3 = czml.Description(bad_data=None) # Add description to CZML packet packet = czml.CZMLPacket(id='the_id') packet.description = d2 self.assertEqual( packet.data(), { 'id': 'the_id', 'description': { 'string': '<h1>Hello World</h1>', 'reference': 'the reference' } }) # Add a description as a dict packet.description = {'string': 'As a dict'} self.assertEqual(packet.data(), { 'id': 'the_id', 'description': { 'string': 'As a dict' } })
def testEllipsoid(self): # Create a new ellipsoid ellipsoid_value = { 'radii': { 'cartesian': [1000.0, 2000.0, 3000.0] }, 'material': {}, 'show': True, } e = czml.Ellipsoid() e.show = True e.radii = czml.Radii(cartesian=[1000, 2000, 3000]) e.material = czml.Material() self.assertEqual(e.data(), ellipsoid_value) # Create a new ellipsoid from an existing ellipsoid e2 = czml.Ellipsoid(**ellipsoid_value) self.assertEqual(e.data(), ellipsoid_value) # Verify you can't create an ellipsoid with a nonsensical value for material. ellipsoid_value['material'] = 2 with self.assertRaises(TypeError): czml.Ellipsoid(**ellipsoid_value) self.assertRaises(TypeError, czml.Ellipsoid, **ellipsoid_value) # Verify you can't create ellipsoids with nonsensical radii ellipsoid_value['material'] = {} ellipsoid_value['radii'] = 5 with self.assertRaises(TypeError): czml.Ellipsoid(**ellipsoid_value) self.assertRaises(TypeError, czml.Ellipsoid, **ellipsoid_value) # Add an ellipsoid to a CZML packet packet = czml.CZMLPacket(id='abc') packet.ellipsoid = e self.assertEqual( packet.data(), { 'id': 'abc', 'ellipsoid': { 'radii': { 'cartesian': [1000.0, 2000.0, 3000.0] }, 'material': {}, 'show': True, }, })
def testPolyline(self): # Create a new polyline sc = czml.SolidColor(color={'rgba': [0, 255, 127, 55]}) m1 = czml.Material(solidColor=sc) c1 = geometry.LineString([(-162, 41, 0), (-151, 43, 0), (-140, 45, 0)]) v1 = czml.Positions(cartographicDegrees=c1) p1 = czml.Polyline(show=True, width=5, followSurface=False, material=m1, positions=v1) self.assertEqual( p1.data(), { 'show': True, 'width': 5, 'followSurface': False, 'material': { 'solidColor': { 'color': { 'rgba': [0, 255, 127, 55] } }, }, 'positions': { 'cartographicDegrees': [-162, 41, 0, -151, 43, 0, -140, 45, 0] }, }) # Create a new polyline pg = czml.PolylineGlow(color={'rgba': [0, 255, 127, 55]}, glowPower=0.25) m2 = czml.Material(polylineGlow=pg) c2 = geometry.LineString([(1.6, 5.3, 10), (2.4, 4.2, 20), (3.8, 3.1, 30)]) v2 = czml.Positions(cartographicRadians=c2) p2 = czml.Polyline(show=False, width=7, followSurface=True, material=m2, positions=v2) self.assertEqual( p2.data(), { 'show': False, 'width': 7, 'followSurface': True, 'material': { 'polylineGlow': { 'color': { 'rgba': [0, 255, 127, 55] }, 'glowPower': 0.25 }, }, 'positions': { 'cartographicRadians': [1.6, 5.3, 10, 2.4, 4.2, 20, 3.8, 3.1, 30] }, }) # Create a polyline from an existing polyline p3 = czml.Polyline() p3.loads(p2.dumps()) self.assertEqual(p3.data(), p2.data()) # Modify an existing polyline po = czml.PolylineOutline(color={'rgba': [0, 255, 127, 55]}, outlineColor={'rgba': [0, 55, 127, 255]}, outlineWidth=4) m3 = czml.Material(polylineOutline=po) c3 = geometry.LineString([(1000, 7500, 90), (2000, 6500, 50), (3000, 5500, 20)]) v3 = czml.Positions(cartesian=c3) p3.material = m3 p3.positions = v3 self.assertEqual( p3.data(), { 'show': False, 'width': 7, 'followSurface': True, 'material': { 'polylineOutline': { 'color': { 'rgba': [0, 255, 127, 55] }, 'outlineColor': { 'rgba': [0, 55, 127, 255] }, 'outlineWidth': 4 }, }, 'positions': { 'cartesian': [1000, 7500, 90, 2000, 6500, 50, 3000, 5500, 20] }, }) # Add a polyline to a CZML packet packet = czml.CZMLPacket(id='abc') packet.polyline = p3 self.assertEqual( packet.data(), { 'id': 'abc', 'polyline': { 'show': False, 'width': 7, 'followSurface': True, 'material': { 'polylineOutline': { 'color': { 'rgba': [0, 255, 127, 55] }, 'outlineColor': { 'rgba': [0, 55, 127, 255] }, 'outlineWidth': 4 }, }, 'positions': { 'cartesian': [1000, 7500, 90, 2000, 6500, 50, 3000, 5500, 20] }, }, })
def testPath(self): # Create a new path sc = czml.SolidColor(color={'rgba': [0, 255, 127, 55]}) m1 = czml.Material(solidColor=sc) c1 = [0, -62, 141, 0, 2, -51, 143, 0, 4, -40, 145, 0] v1 = czml.Position(cartographicDegrees=c1) p1 = czml.Path(show=True, width=5, leadTime=2, trailTime=6, resolution=3, material=m1, position=v1) self.assertEqual( p1.data(), { 'show': True, 'width': 5, 'leadTime': 2, 'trailTime': 6, 'resolution': 3, 'material': { 'solidColor': { 'color': { 'rgba': [0, 255, 127, 55] } }, }, 'position': { 'cartographicDegrees': [0, -62, 141, 0, 2, -51, 143, 0, 4, -40, 145, 0] }, }) # Create a new path from an existing path p2 = czml.Path() p2.loads(p1.dumps()) self.assertEqual(p2.data(), p1.data()) # Modify an existing path po = czml.PolylineOutline(color={'rgba': [0, 255, 127, 55]}, outlineColor={'rgba': [0, 55, 127, 255]}, outlineWidth=4) m2 = czml.Material(polylineOutline=po) c2 = [0, 1000, 7500, 90, 4, 2000, 6500, 50, 8, 3000, 5500, 20] v2 = czml.Position(cartesian=c2) p2.show = False p2.material = m2 p2.position = v2 self.assertEqual( p2.data(), { 'show': False, 'width': 5, 'leadTime': 2, 'trailTime': 6, 'resolution': 3, 'material': { 'polylineOutline': { 'color': { 'rgba': [0, 255, 127, 55] }, 'outlineColor': { 'rgba': [0, 55, 127, 255] }, 'outlineWidth': 4 }, }, 'position': { 'cartesian': [0, 1000, 7500, 90, 4, 2000, 6500, 50, 8, 3000, 5500, 20] }, }) # Add a path to a CZML packet packet = czml.CZMLPacket(id='abc') packet.path = p2 self.assertEqual( packet.data(), { 'id': 'abc', 'path': { 'show': False, 'width': 5, 'leadTime': 2, 'trailTime': 6, 'resolution': 3, 'material': { 'polylineOutline': { 'color': { 'rgba': [0, 255, 127, 55] }, 'outlineColor': { 'rgba': [0, 55, 127, 255] }, 'outlineWidth': 4 }, }, 'position': { 'cartesian': [ 0, 1000, 7500, 90, 4, 2000, 6500, 50, 8, 3000, 5500, 20 ] }, }, })
from czml import czml doc = czml.CZML() packet1 = czml.CZMLPacket(id='document', version='1.0') doc.packets.append(packet1) # Create and append a billboard packet def create(obj_id, longitude, latitude, height): packet2 = czml.CZMLPacket(id=obj_id) packet2.name = "BEIDOU1" lb = czml.Label(text="北斗卫星", show=True) lb.scale = 0.5 lb.pixelOffset = {'cartesian2': [50, -30]} packet2.label = lb packet2.position = {"cartographicDegrees": [longitude, latitude, height]} md = czml.Model() md.gltf = "../../Models/a2100.gltf" md.maximumScale = 20000 md.minimumPixelSize = 64 packet2.model = md doc.packets.append(packet2) create("Satellite2", 105.2, 39.2, 20000) # Write the CZML document to a file filename = "test.czml" doc.write(filename)
def czml(self): doc = czml.CZML(); iso = self.date.isoformat() # Generate time-specific lists for various objects central_polyline_degrees = [] north_polyline_degrees = [] south_polyline_degrees = [] ellipse_position = [] ellipse_semiMajorAxis = [] ellipse_semiMinorAxis = [] ellipse_rotation = [] for t in range(len(self.time)): time = iso + "T" + self.time[t] + ":00Z" # Define polyline waypoints only where data exist if self.position['north'][t] != None: north_polyline_degrees += [self.position['north'][t][0], self.position['north'][t][1], 0.0] if self.position['central'][t] != None: central_polyline_degrees += [self.position['central'][t][0], self.position['central'][t][1], 0.0] if self.position['south'][t] != None: south_polyline_degrees += [self.position['south'][t][0], self.position['south'][t][1], 0.0] # Define ellipse positions and attributes for every time in the interval, using limits where necessary use_limit = min(int(math.floor(t/(len(self.time)/2))),1) if self.position['north'][t] == None: north = self.limits['north'][use_limit] else: north = self.position['north'][t] if self.position['central'][t] == None: central = self.limits['central'][use_limit] else: central = self.position['central'][t] if self.position['south'][t] == None: south = self.limits['south'][use_limit] else: south = self.position['south'][t] # Approximate ellipse semiMajorAxis from vincenty distance between limit polylines north2 = (north[1], north[0]) south2 = (south[1], south[0]) semi_major_axis = vincenty(north2, south2).meters / 2 # Approximate elipse semiMinorAxis from sun altitude (probably way wrong!) ellipse_axis_ratio = self.sun_altitude[t] / 90 semi_minor_axis = semi_major_axis * ellipse_axis_ratio # Approximate ellipse rotation using basic spheroid (TODO: replace with WGS-84) # Calculate bearing in both directions and average them nlat = north[1]/180 * math.pi; nlon = north[0]/180 * math.pi; clat = central[1]/180 * math.pi; clon = central[0]/180 * math.pi; slat = south[1]/180 * math.pi; slon = south[0]/180 * math.pi; y = math.sin(slon-nlon) * math.cos(slat); x = math.cos(nlat) * math.sin(slat) - math.sin(nlat) * math.cos(slat) * math.cos(slon-nlon); initial_bearing = math.atan2(y, x) if (initial_bearing < 0): initial_bearing += math.pi * 2 y = math.sin(nlon-slon) * math.cos(nlat); x = math.cos(slat) * math.sin(nlat) - math.sin(slat) * math.cos(nlat) * math.cos(nlon-slon); final_bearing = math.atan2(y, x) - math.pi if (final_bearing < 0): final_bearing += math.pi * 2 rotation = -1 * ((initial_bearing + final_bearing) / 2 - (math.pi / 2)) ellipse_position += [time, central[0], central[1], 0.0] ellipse_semiMajorAxis += [time, round(semi_major_axis, 3)] ellipse_semiMinorAxis += [time, round(semi_minor_axis, 3)] ellipse_rotation += [time, round(rotation, 3)] # Generate document packet with clock start_time = iso + "T" + self.time[0] + ":00Z" end_time = iso + "T" + self.time[-1] + ":00Z" packet = czml.CZMLPacket(id='document',version='1.0') c = czml.Clock() c.multiplier = 300 c.range = "LOOP_STOP" c.step = "SYSTEM_CLOCK_MULTIPLIER" c.currentTime = start_time c.interval = start_time + "/" + end_time packet.clock = c doc.packets.append(packet) # Generate a polyline packet for the north and south polylines, connected and filled limit_polyline_degrees = list(north_polyline_degrees) point = len(south_polyline_degrees)/3 while (point > 0): offset = (point-1) * 3 limit_polyline_degrees += [ south_polyline_degrees[offset], south_polyline_degrees[offset+1], south_polyline_degrees[offset+2] ] point -= 1 packet_id = iso + '_bounds_polygon' packet = czml.CZMLPacket(id=packet_id) boc = czml.Color(rgba=(232, 72, 68, 255)) bsc = czml.SolidColor(color=czml.Color(rgba=(0, 0, 0, 66))) bmat = czml.Material(solidColor=bsc) bdeg = limit_polyline_degrees bpos = czml.Positions(cartographicDegrees=bdeg) bpg = czml.Polygon(show=True, height=0, outline=True, outlineColor=boc, outlineWidth=2, material=bmat, positions=bpos) packet.polygon = bpg doc.packets.append(packet) # Generate central polyline packet packet_id = iso + '_central_polyline' packet = czml.CZMLPacket(id=packet_id) csc = czml.SolidColor(color=czml.Color(rgba=(241, 226, 57, 255))) cmat = czml.Material(solidColor=csc) cpos = czml.Positions(cartographicDegrees=central_polyline_degrees) cpl = czml.Polyline(show=True, width=4, followSurface=True, material=cmat, positions=cpos) packet.polyline = cpl doc.packets.append(packet) # Generate ellipse shadow packet packet_id = iso + '_shadow_ellipse' packet = czml.CZMLPacket(id=packet_id) esc = czml.SolidColor(color=czml.Color(rgba=(0, 0, 0, 160))) emat = czml.Material(solidColor=esc) xmaj = czml.Number(ellipse_semiMajorAxis) xmin = czml.Number(ellipse_semiMinorAxis) rot = czml.Number(ellipse_rotation) ell = czml.Ellipse(show=True, fill=True, granularity=0.002, material=emat, semiMajorAxis=xmaj, semiMinorAxis=xmin, rotation=rot) packet.ellipse = ell packet.position = czml.Position(cartographicDegrees=ellipse_position) doc.packets.append(packet) return list(doc.data())
def add_nodes(self, demographics, population_as_size=True, with_altitude=False, processor=None, namer=None): """Add demographics node data to the CZMLWriter object. DEPRECATED. This (DEPRECATED) method allows you to add node representations to a CZML output file, where the node point size is relative to the node's InitialPopulation. Since the Vis-Tools client does this in a much more flexible way, this method is deprecated, but may be educational for those looking to extend the CZMLWriter class. Returns: None Args: demographics (Demographics) A Demographics object with node data. population_as_size (bool): True to scale point size by InitialPopulation, fixed size otherwise with_altitude: True to emit node coordinates including their altitude, false to just emit them with default altitude processor: None or a function that processes the node and and the czml wrapper into a new CZML packet. namer: None or a function that converts a node into a name string """ pop_adjusted_max = demographics.calc_adjusted_pop_max() pop_range = pop_adjusted_max - demographics.population_min size_px_min = 6 size_px_max = 32 size_range = size_px_max - size_px_min for node in demographics.Nodes: name = repr(node["NodeID"]) if namer is not None: name = namer(node, name) attrs = node["NodeAttributes"] lon = attrs["Longitude"] lat = attrs["Latitude"] alt = attrs["Altitude"] if with_altitude else 0 if processor is None: packet = czml.CZMLPacket( id=name, name=name, position={"cartographicDegrees": [lon, lat, alt]}) size = CZMLWriter.k_default_node_point_size if population_as_size: pop = attrs["InitialPopulation"] if pop > pop_adjusted_max: pop = pop_adjusted_max norm_pop = (pop - demographics.population_min) / pop_range size = size_px_min + norm_pop * size_range # show=True is required below packet.point = czml.Point(pixelSize=size, show=True) else: packet = processor(self, czml, node) self.doc.packets.append(packet) if self._verbose: print("CZMLWriter.add_nodes: Added %s node%s" %\ (len(demographics.Nodes), "" if len(demographics.Nodes) == 1 else "s"))
def add_event_markers(self, event_recorder, demographics, event_name, marker, color, placement, duration_days, with_altitude=False): """Adds event marker animation to a CZML output. This function looks for a particular event in an event recorder report and emits an animation that puts a marker somewhere around the node and leaves it there for a specified period after the event. Returns: Number of event markers in animation layer Args: event_recorder (CSVReport): Event recorder report object demographics (Demographics): Demographics object with node data event_name (str): Name of event to mark in the animation marker (str): Name of a marker icon ("Triangle" or "Cross") color (str): Any HTML or SVG named color (e.g. "red") or a CSS color string (e.g. "#ff0000") placement (str): Placement about the node point ("Top", "Left", "Bottom" or "Right") duration_days (int): Number of days for which the symbol should remain about the node after it fires. with_altitude (bool): True to set the symbol elevations to match the node altitude, or default altitude otherwise. """ czml.Billboard._properties =\ ('show', 'image', 'color', 'scale', 'verticalOrigin', 'horizontalOrigin') count = 0 timestep_offset = int(event_recorder.rows[0]["Time"]) if color in NamedColors.__dict__: color = NamedColors.__dict__[color] else: color = Color.from_html_hash(color) for event in event_recorder: if not event["Event_Name"] == event_name: continue if event["Node_ID"] in demographics: timestep = int(event["Time"]) - timestep_offset node = demographics[event["Node_ID"]] availability = self._timestep_to_iso(timestep) + "/" +\ self._timestep_to_iso(timestep + duration_days) attrs = node["NodeAttributes"] lon = attrs["Longitude"] lat = attrs["Latitude"] alt = attrs["Altitude"] if with_altitude else 0 ni_packet = czml.CZMLPacket( id=repr(count), availability=availability, position={ "epoch": self._timestep_to_iso(timestep), "cartographicDegrees": [lon, lat, alt] }) bb = czml.Billboard(image="/vistools/image/" + marker + placement + ".png", color={"rgba": color.to_rgba_array()}) bb.verticalOrigin = self._vertical_origin(placement) bb.horizontalOrigin = self._horizontal_origin(placement) ni_packet.billboard = bb self.doc.packets.append(ni_packet) count += 1 if self._verbose: print("CZMLWriter.add_event_markers: %d event markers added." %\ count) return count
other_point, distance = get_closest_point((points[-1], points[-2]), index) if distance < 0.04: points.append(other_point[0]) points.append(other_point[1]) points.append(0) return points with open("custom_rails_202010281149.json", 'r') as f: payload = json.loads(f.read())['custom_rails'] doc = czml.CZML() initial_packet = czml.CZMLPacket(id="document", version="1.0") initial_packet.clock = { "step": "SYSTEM_CLOCK_MULTIPLIER", #"step": 1, "range": "LOOP_STOP", "multiplier": 2160000 / 600, "interval": "2020-01-01/2035-01-01", "currentTime": "2020-01-01" } initial_packet.name = "IORAMA Rails" doc.packets.append(initial_packet) # fill cached points for rail in payload: points_db.append(multilinestring_to_positions(rail, False, -1)) segments.append(
def add_vector_migrations(self, vector_migrations, demographics, migration_duration_timesteps, dot_color, dot_size_pixels, path_color, path_thickness_pixels, path_trail_time_factor): """Adds vector cohort migration animations to a CZML output. This function, given vector migrations in a particular format and a demographics file, adds "comet" animations for migration events. This function expects the following fields in vector_migrations: * Time (int): the timestep of the beginning of the migration event * FromNodeID (int): the node ID from which the migration emanates * ToNodeID (int): the node ID to which the migration completes Returns: Number of vector cohort migrations in animation layer Args: vector_migrations (CSVReport): The ReportVectorMigrations.csv report. demographics (Demographics): The Demographics object describing the nodes. migration_duration_timesteps (int): The duration of the migration animations in timesteps. dot_color (string): A CSS #rrggbb color for the comet dot. dot_size_pixels (int): Size in pixels of comet dot. path_color (string): A CSS #rrggbb color for the comet tail. path_thickness_pixels (float): Thickness in pixels of comet tail. path_trail_time_factor (float): Length of trail as a multiple of the migration_duration. E.g. if this is 1.0, the trail length will be the full distance from source node to the destination node. If 0.5, the trail length will be half the distance between the nodes. """ count = 0 for row in vector_migrations: timestep = int(row["Time"]) from_node_id = row["FromNodeID"] to_node_id = row["ToNodeID"] if not (from_node_id in demographics and to_node_id in demographics): continue from_node = demographics[from_node_id] to_node = demographics[to_node_id] dur_seconds = migration_duration_timesteps * 60 * 60 * 24 trail_seconds = dur_seconds * path_trail_time_factor availability = self._timestep_to_iso(timestep) + "/" +\ self._timestep_to_iso(timestep + migration_duration_timesteps) id_txt = "%s-%s@%d_%d" % (from_node_id, to_node_id, timestep, count) # The thing to remember about paths is that their initial duration # is going to be availability, but then they are going to be around # for an *additional* trailTime seconds. So the color fade in the # path needs to run for dur_seconds + trailTime. mig_path = czml.CZMLPacket( id=id_txt, availability=availability, position={ "epoch": self._timestep_to_iso(timestep), "cartographicDegrees": [ 0, # in seconds from_node["NodeAttributes"]["Longitude"], from_node["NodeAttributes"]["Latitude"], 0, # altitude dur_seconds, to_node["NodeAttributes"]["Longitude"], to_node["NodeAttributes"]["Latitude"], 0 # altitude ] }) dc = Color.from_html_hash(dot_color) pc = Color.from_html_hash(path_color) pt = czml.Point(pixelSize=dot_size_pixels, show=True, color={ "epoch": self._timestep_to_iso(timestep), "rgba": [ 0, dc.r, dc.g, dc.b, 255, dur_seconds, dc.r, dc.g, dc.b, 0 ] }) path = czml.Path(leadTime=0, trailTime=trail_seconds, resolution=CZMLWriter.k_default_clock_multiplier, material={ "solidColor": { "color": { "epoch": self._timestep_to_iso(timestep), "rgba": [ 0, pc.r, pc.g, pc.b, 255, dur_seconds + trail_seconds, pc.r, pc.g, pc.b, 0 ] } } }, width=path_thickness_pixels) mig_path.point = pt mig_path.path = path self.doc.packets.append(mig_path) count += 1 if self._verbose: print("CZMLWriter.add_vector_migrations: %d migrations added." %\ count) return count
def geojsonToCzmlTotal(file, total=True): doc = czml.CZML() clock={ 'interval': '2019-12-31T00:00:00Z/2020-08-16T23:59:59Z', 'currentTime': '2019-12-31T00:00:00Z', 'multiplier': 320000, 'range': 'LOOP_STOP', 'step': 'SYSTEM_CLOCK_MULTIPLIER' } packet1 = czml.CZMLPacket( id='document', version='1.0', clock=clock ) doc.packets.append(packet1) with open(file) as f: ids = {} data = json.load(f) for feature in data['features']: total_values = 0 if total: total_values = feature['properties']['total_cases'] if feature['properties']['total_cases'] != None else 0 else: total_values = feature['properties']['total_deaths'] if feature['properties']['total_deaths'] != None else 0 description = 'Total deaths on ' + feature['properties']['date'] + ' is ' + str(total_values) description= '\ <h2>General Details:</h2> \ <p>\ Date: {date} <br /> \ Total cases: {total_cases} <br /> \ Total cases/million: {total_cases_pm} <br /> \ Total deaths: {total_deaths} <br /> \ Total deaths/million: {total_deaths_pm} <br /> \ New cases: {new_cases} <br /> \ New deaths: {new_deaths} <br /> \ </p>\ <h2>Demographic Details:</h2> \ <p> \ Population: {population} <br /> \ Median age: {median_age} <br /> \ Hospital beds/thoudsand: {hospital_beds_per_thousand} \ </p> \ '.format( date=feature['properties']['date'], total_cases=feature['properties']['total_cases'], total_cases_pm=feature['properties']['total_cases_per_million'], total_deaths=feature['properties']['total_deaths'], total_deaths_pm=feature['properties']['total_deaths_per_million'], new_cases=feature['properties']['new_cases'], new_deaths=feature['properties']['new_deaths'], population=feature['properties']['population'], median_age=feature['properties']['median_age'], hospital_beds_per_thousand=feature['properties']['hospital_beds_per_thousand'], ) id = 0 if feature['properties']['Address'] in ids: ids[feature['properties']['Address']] += 1 id = ids[feature['properties']['Address']] else: ids[feature['properties']['Address']] = 0 packet = czml.CZMLPacket( id=feature['properties']['Address']+str(id), name=feature['properties']['Address'], description=description, availability=feature['properties']['date'] + 'T00:00:00.000Z'+ '/' + feature['properties']['date'] + 'T23:59:59.999Z' ) # pixel_size=0 # if total_values > 5: # pixel_size = math.log(total_values) point = czml.Point( show=True, pixelSize=clamp(total_values, 0, 100) ) # Coloring based on number of cases color = [255, 0, 0, 65] if total_values < 50: color = [52, 235, 61, 65] elif total_values >= 50 and total_values < 200: color = [235, 222, 52, 65] elif total_values >= 200 and total_values < 2000: color = [235, 155, 52, 65] else: color = [235, 76, 52, 65] point.color = {'rgba': color} packet.point = point packet.position = { 'cartographicDegrees': [ feature['geometry']['coordinates'][0], feature['geometry']['coordinates'][1], 0.0 ] } doc.packets.append(packet) # Write the czml document to a file if total: filename = "./data_total.czml" doc.write(filename) else: filename = "./data_deaths.czml" doc.write(filename)
def init(): packet1 = czml.CZMLPacket(id='document', version='1.0') doc.packets.append(packet1)
def testEllipse(self): # Create a new ellipse sc = czml.SolidColor(color={'rgba': [127, 127, 127, 255]}) mat1 = czml.Material(solidColor=sc) pts1 = [50, 20, 2] pos1 = czml.Position(cartographicDegrees=pts1) ell1 = czml.Ellipse(show=True, fill=True, height=50, extrudedHeight=200, outline=True, outlineColor={'rgba': [0, 255, 127, 55]}, semiMajorAxis=150, semiMinorAxis=75, numberOfVerticalLines=800, rotation=1.2, material=mat1, position=pos1) self.assertEqual( ell1.data(), { 'show': True, 'fill': True, 'outline': True, 'height': 50, 'extrudedHeight': 200, 'rotation': 1.2, 'semiMajorAxis': 150, 'semiMinorAxis': 75, 'numberOfVerticalLines': 800, 'outlineColor': { 'rgba': [0, 255, 127, 55] }, 'material': { 'solidColor': { 'color': { 'rgba': [127, 127, 127, 255] } }, }, 'position': { 'cartographicDegrees': [50, 20, 2] }, }) # Create a new ellipse from an existing ellipse ell2 = czml.Ellipse() ell2.loads(ell1.dumps()) self.assertEqual(ell2.data(), ell1.data()) # Modify an existing ellipse strp = czml.Stripe(evenColor={'rgba': [127, 55, 255, 255]}, oddColor={'rgba': [127, 255, 55, 127]}, offset=1.3, repeat=64, orientation='VERTICAL') mat2 = czml.Material(stripe=strp) pts2 = [0, 1.5, 1.2, 0, 2, 1.6, 1.3, 0, 4, 1.5, 1.3, 0, 6, 1.6, 1.2, 0] pos2 = czml.Position(cartographicRadians=pts2) ell2.material = mat2 ell2.position = pos2 ell2.perPositionHeight = False ell2.height = 7 ell2.extrudedHeight = 30 ell2.semiMajorAxis = 600 ell2.semiMinorAxis = 400 self.assertEqual( ell2.data(), { 'show': True, 'fill': True, 'outline': True, 'height': 7, 'extrudedHeight': 30, 'rotation': 1.2, 'semiMajorAxis': 600, 'semiMinorAxis': 400, 'numberOfVerticalLines': 800, 'outlineColor': { 'rgba': [0, 255, 127, 55] }, 'material': { 'stripe': { 'evenColor': { 'rgba': [127, 55, 255, 255] }, 'oddColor': { 'rgba': [127, 255, 55, 127] }, 'offset': 1.3, 'repeat': 64, 'orientation': 'VERTICAL' }, }, 'position': { 'cartographicRadians': [ 0, 1.5, 1.2, 0, 2, 1.6, 1.3, 0, 4, 1.5, 1.3, 0, 6, 1.6, 1.2, 0 ] }, }) # Add an ellipse to a CZML packet packet = czml.CZMLPacket(id='abc') packet.ellipse = ell2 self.assertEqual( packet.data(), { 'id': 'abc', 'ellipse': { 'show': True, 'fill': True, 'outline': True, 'height': 7, 'extrudedHeight': 30, 'rotation': 1.2, 'semiMajorAxis': 600, 'semiMinorAxis': 400, 'numberOfVerticalLines': 800, 'outlineColor': { 'rgba': [0, 255, 127, 55] }, 'material': { 'stripe': { 'evenColor': { 'rgba': [127, 55, 255, 255] }, 'oddColor': { 'rgba': [127, 255, 55, 127] }, 'offset': 1.3, 'repeat': 64, 'orientation': 'VERTICAL' }, }, 'position': { 'cartographicRadians': [ 0, 1.5, 1.2, 0, 2, 1.6, 1.3, 0, 4, 1.5, 1.3, 0, 6, 1.6, 1.2, 0 ] }, }, })
doc = czml.CZML() # In[2]: clock = { "step": "SYSTEM_CLOCK_MULTIPLIER", "range": "LOOP_STOP", "multiplier": 2160000, "interval": "2015-01-01/2015-12-31", "currentTime": "2015-01-01" } # In[3]: # Create and append the document packet packet1 = czml.CZMLPacket(id='document', version='1.0', clock=clock) # In[4]: packet1.dumps() # In[5]: doc.packets.append(packet1) # In[6]: packet2 = czml.CZMLPacket(id='flycatcher', availability="2015-01-01/2015-12-31") # In[7]:
def add_weighted_network(self, demographics, network, gradient_spec, opacity_func): """Adds a weighted network visualization layer to a CZML output. This method emits a CZML animation that provides a visual representation of a weighted network between nodes. Returns: Number of network segments added Args: demographics (Demographics): Demographics object for nodes. network (array): array of objects:: { from: <from-node-id>, to: <to-node-id>, weight: <float-weight> } gradient_spec (str): gradient spec for a gradient with which to color the network lines. opacity_func (function): function(weight, norm_weight) that returns the desired opacity in range [0,1]. """ # First pass - collect min/max rate min_weight = network[0]["weight"] max_weight = network[0]["weight"] for segment in network: weight = segment["weight"] min_weight = weight if weight < min_weight else min_weight max_weight = weight if weight > max_weight else max_weight weight_range = max_weight - min_weight # Second pass - precalculate norm_weight and opacity for segment in network: weight = segment["weight"] norm_weight = (weight - min_weight) / weight_range segment["norm_weight"] = norm_weight segment["opacity"] = opacity_func(weight, norm_weight) # Sort network by opacity, lowest opacity first # network.sort(key=lambda seg: seg["opacity"]) def sort_func(a, b): diff = a["opacity"] - b["opacity"] if diff < 0: return -1 elif diff == 0: return 0 else: return 1 if sys.version_info.major == 3: # python 3: use a key function network = sorted(network, key=functools.cmp_to_key(sort_func)) else: # python 2: use a cmp function network = sorted(network, cmp=sort_func) gradient = Gradient(gradient_spec) count = 0 for segment in network: from_node = demographics[segment["from"]] to_node = demographics[segment["to"]] color = gradient.sample(segment["norm_weight"]).to_rgba_array() color[3] = int(segment["opacity"] * 255) # id = repr(segment["from"]) + "-" + repr(segment["to"]) id = count packet = czml.CZMLPacket(id=id) positions = { "cartographicDegrees": [ from_node["NodeAttributes"]["Longitude"], from_node["NodeAttributes"]["Latitude"], 0, to_node["NodeAttributes"]["Longitude"], to_node["NodeAttributes"]["Latitude"], 0 ] } line = czml.Polyline( show=True, positions=positions, width=1, material={"solidColor": { "color": { "rgba": color } }}) packet.polyline = line self.doc.packets.append(packet) count += 1 if self._verbose: print("CZMLWriter.add_network: %d network segments added." % count) return count
def testPolygon(self): # Create a new polygon img = czml.Image(image='http://localhost/img.png', repeat=2) mat = czml.Material(image=img) pts = geometry.LineString([(50, 20, 2), (60, 30, 3), (50, 30, 4), (60, 20, 5)]) pos = czml.Positions(cartographicDegrees=pts) col = {'rgba': [0, 255, 127, 55]} pol = czml.Polygon(show=True, material=mat, positions=pos, perPositionHeight=True, fill=True, outline=True, outlineColor=col) self.assertEqual( pol.data(), { 'show': True, 'fill': True, 'outline': True, 'perPositionHeight': True, 'outlineColor': { 'rgba': [0, 255, 127, 55] }, 'material': { 'image': { 'image': 'http://localhost/img.png', 'repeat': 2 }, }, 'positions': { 'cartographicDegrees': [50, 20, 2, 60, 30, 3, 50, 30, 4, 60, 20, 5] }, }) # Create a new polygon from an existing polygon pol2 = czml.Polygon() pol2.loads(pol.dumps()) self.assertEqual(pol2.data(), pol.data()) # Modify an existing polygon grid = czml.Grid(color={'rgba': [0, 55, 127, 255]}, cellAlpha=0.4, lineCount=5, lineThickness=2, lineOffset=0.3) mat2 = czml.Material(grid=grid) pts2 = geometry.LineString([(1.5, 1.2, 0), (1.6, 1.3, 0), (1.5, 1.3, 0), (1.6, 1.2, 0)]) pos2 = czml.Positions(cartographicRadians=pts2) pol2.material = mat2 pol2.positions = pos2 pol2.perPositionHeight = False pol2.height = 7 pol2.extrudedHeight = 30 self.assertEqual( pol2.data(), { 'show': True, 'fill': True, 'outline': True, 'perPositionHeight': False, 'height': 7, 'extrudedHeight': 30, 'outlineColor': { 'rgba': [0, 255, 127, 55] }, 'material': { 'grid': { 'color': { 'rgba': [0, 55, 127, 255] }, 'cellAlpha': 0.4, 'lineCount': 5, 'lineThickness': 2, 'lineOffset': 0.3 }, }, 'positions': { 'cartographicRadians': [1.5, 1.2, 0, 1.6, 1.3, 0, 1.5, 1.3, 0, 1.6, 1.2, 0] }, }) # Add a polygon to a CZML packet packet = czml.CZMLPacket(id='abc') packet.polygon = pol2 self.assertEqual( packet.data(), { 'id': 'abc', 'polygon': { 'show': True, 'fill': True, 'outline': True, 'perPositionHeight': False, 'height': 7, 'extrudedHeight': 30, 'outlineColor': { 'rgba': [0, 255, 127, 55] }, 'material': { 'grid': { 'color': { 'rgba': [0, 55, 127, 255] }, 'cellAlpha': 0.4, 'lineCount': 5, 'lineThickness': 2, 'lineOffset': 0.3 }, }, 'positions': { 'cartographicRadians': [1.5, 1.2, 0, 1.6, 1.3, 0, 1.5, 1.3, 0, 1.6, 1.2, 0] }, }, })
def testCZMLPacket(self): p = czml.CZMLPacket(id='abc') self.assertEqual(p.dumps(), '{"id": "abc"}') bb = czml.Billboard() bb.image = 'http://localhost/img.png' bb.scale = 0.7 bb.show = True p.billboard = bb self.assertEqual(p.data(), {'billboard': {'image': 'http://localhost/img.png', 'scale': 0.7, 'show': True}, 'id': 'abc'}) p2 = czml.CZMLPacket(id='abc') p2.loads(p.dumps()) self.assertEqual(p.data(), p2.data()) pos = czml.Position() coords = [7.0, 0.0, 1.0, 2.0, 6.0, 3.0, 4.0, 5.0] pos.cartesian = coords p.position = pos l = czml.Label() l.text = 'test label' l.show = False p.label = l self.assertEqual(p.data(), {'billboard': {'image': 'http://localhost/img.png', 'scale': 0.7, 'show': True}, 'id': 'abc', 'label': {'show': False, 'text': 'test label'}, 'position': {'cartesian': [7.0, 0.0, 1.0, 2.0, 6.0, 3.0, 4.0, 5.0]}, }) p2.loads(p.dumps()) self.assertEqual(p.data(), p2.data()) p3 = czml.CZMLPacket(id='cde') p3.point = {'color': {'rgba': [0, 255, 127, 55]}, 'show': True} self.assertEqual(p3.data(), {'id': 'cde', 'point': {'color': {'rgba': [0, 255, 127, 55]}, 'show': True}}) p32 = czml.CZMLPacket(id='abc') p32.loads(p3.dumps()) self.assertEqual(p3.data(), p32.data()) p4 = czml.CZMLPacket(id='defg') pl = czml.Polyline() pl.color = {'rgba': [0, 255, 127, 55]} pl.width = 10 pl.outlineWidth = 2 pl.show = True v = czml.VertexPositions() v.cartographicDegrees = [0.0, 0.0, .0, 1.0, 1.0, 1.0] p4.vertexPositions = v p4.polyline = pl self.assertEqual(p4.data(), {'polyline': {'color': {'rgba': [0, 255, 127, 55]}, 'width': 10, 'outlineWidth': 2, 'show': True}, 'id': 'defg', 'vertexPositions': {'cartographicDegrees': [0.0, 0.0, 0.0, 1.0, 1.0, 1.0]} }) p42 = czml.CZMLPacket(id='abc') p42.loads(p4.dumps()) self.assertEqual(p4.data(), p42.data()) p5 = czml.CZMLPacket(id='efgh') p5.vertexPositions = v poly = czml.Polygon(color={'rgba': [0, 255, 127, 55]}) p5.polygon = poly self.assertEqual(p5.data(), {'polygon': {'material': {'solidColor': {'color': {'rgba': [0, 255, 127, 55]}}}}, 'id': 'efgh', 'vertexPositions': {'cartographicDegrees': [0.0, 0.0, 0.0, 1.0, 1.0, 1.0]}}) p52 = czml.CZMLPacket(id='abc') p52.loads(p5.dumps()) self.assertEqual(p5.data(), p52.data()) return p
def add_migrations(self, migrations, demographics, with_altitude=False): """Adds migration animations to a CZML output. This function, given migrations in a particular format and demographics, adds "comet" animations for migration events. Returns: Number of infected human migrations in animation layer Args: migrations (obj): An object that describes migrations (see below) demographics (Demographics): A Demographics object describing nodes with_altitude: True to respect the altitude in the node coordinates migrations is a dictionary where the keys are <timestep> and the values are objects with keys <from_node_id>-<to_node_id> and the values are the number of migrations at that timestep from from_node_id to to_node_id. See MigrationHelpers.py for more details. Todo: * Color customization (comet heads, comet tails) * Duration customization (comet tails) """ count = 0 for timestep in list(migrations.keys()): timestep_rec = migrations[timestep] for migration_key in list(timestep_rec.keys()): from_node_id, to_node_id = migration_key.split("-") if not (from_node_id in demographics and to_node_id in demographics): continue from_node = demographics[from_node_id] to_node = demographics[to_node_id] availability = self._timestep_to_iso(timestep) + "/" +\ self._timestep_to_iso(int(timestep) + CZMLWriter.k_default_migration_duration_days) id_txt = "%s_%d" % (migration_key, count) # The thing to remember about paths is that their initial # duration is going to be availability, but then they are going # to be around for an *additional* trailTime seconds. So the # color fade in the path needs to run for dur_seconds + # trailTime. mig_path = czml.CZMLPacket( id=id_txt, availability=availability, position={ "epoch": self._timestep_to_iso(timestep), "cartographicDegrees": [ 0, # seconds from_node["NodeAttributes"]["Longitude"], from_node["NodeAttributes"]["Latitude"], from_node["NodeAttributes"]["Altitude"] if with_altitude else 0, CZMLWriter.k_default_migration_duration_seconds, to_node["NodeAttributes"]["Longitude"], to_node["NodeAttributes"]["Latitude"], to_node["NodeAttributes"]["Altitude"] if with_altitude else 0 ] }) pt = czml.Point( pixelSize=10, show=True, color={ "epoch": self._timestep_to_iso(timestep), "rgba": [ 0, 186, 127, 183, 255, CZMLWriter.k_default_migration_duration_seconds, 186, 127, 183, 0 ] }) path = czml.Path( leadTime=0, trailTime=60 * 60 * 12, # half-day resolution=CZMLWriter.k_default_clock_multiplier, material={ "solidColor": { "color": { "epoch": self._timestep_to_iso(timestep), "rgba": [ 0, 255, 255, 255, 255, CZMLWriter. k_default_migration_duration_seconds + 60 * 60 * 12, 255, 255, 255, 0 ] } } }, width=2.5) mig_path.point = pt mig_path.path = path self.doc.packets.append(mig_path) count += 1 if self._verbose: print("CZMLWriter.add_migrations: %d migrations added." % count) return count
def testPoint(self): # Create a new point point = czml.Point() point.color = {'rgba': [0, 255, 127, 55]} self.assertEqual(point.data(), { 'color': { 'rgba': [0, 255, 127, 55] }, 'show': False }) point.outlineColor = {'rgbaf': [0.0, 0.255, 0.127, 0.55]} self.assertEqual( point.data(), { 'color': { 'rgba': [0, 255, 127, 55] }, 'outlineColor': { 'rgbaf': [0.0, 0.255, 0.127, 0.55] }, 'show': False }) # Modify an existing point point.pixelSize = 10 point.outlineWidth = 2 point.show = True self.assertEqual( point.data(), { 'color': { 'rgba': [0, 255, 127, 55] }, 'pixelSize': 10, 'outlineColor': { 'rgbaf': [0.0, 0.255, 0.127, 0.55] }, 'outlineWidth': 2, 'show': True }) # Create a new point from an existing point p2 = czml.Point() p2.loads(point.dumps()) self.assertEqual(point.data(), p2.data()) # Add a point to a CZML packet packet = czml.CZMLPacket(id='abc') packet.point = p2 self.assertEqual( packet.data(), { 'id': 'abc', 'point': { 'color': { 'rgba': [0, 255, 127, 55] }, 'pixelSize': 10, 'outlineColor': { 'rgbaf': [0.0, 0.255, 0.127, 0.55] }, 'outlineWidth': 2, 'show': True }, })
def add_simplified_vector_migrations(self, vector_migrations, demographics, migration_duration_timesteps, arrow_color, arrow_thickness_pixels): """Adds vector cohort migration animations to a CZML output. This function, given vector migrations in a particular format and a demographics file, adds "comet" animations for migration events. This function expects the following fields in vector_migrations: * Time (int): the timestep of the beginning of the migration event * FromNodeID (int): the node ID from which the migration emanates * ToNodeID (int): the node ID to which the migration completes Returns: Number of vector cohort migrations in animation layer Args: vector_migrations (CSVReport): The ReportVectorMigrations.csv report. demographics (Demographics): The Demographics object describing the nodes. migration_duration_timesteps (int): The duration of the migration animations in timesteps. arrow_color (string): A CSS #rrggbb color for the migration arrow. arrow_thickness_pixels (float): Thickness in pixels of comet tail. """ czml.Material._properties = \ ('grid', 'image', 'stripe', 'solidColor', 'polylineGlow', 'polylineOutline', 'polylineArrow') # This is a little ugly - I run-time extend Material with a # PolylineArrow property, since the one in module czml lacks that. class PolylineArrow(czml._CZMLBaseObject): """Colors the line with a color and an arrow.""" _color = None _properties = ('color', ) czml.Material._polylineArrow = None czml.Material.polylineArrow = czml.class_property( PolylineArrow, 'polylineArrow', doc="""Colors the line with a color and an arrow.""") count = 0 for row in vector_migrations: timestep = int(row["Time"]) from_node_id = row["FromNodeID"] to_node_id = row["ToNodeID"] if not (from_node_id in demographics and to_node_id in demographics): continue from_node = demographics[from_node_id] to_node = demographics[to_node_id] dur_seconds = migration_duration_timesteps * 60 * 60 * 24 availability = self._timestep_to_iso(timestep) + "/" +\ self._timestep_to_iso(timestep + migration_duration_timesteps) id_txt = "%s-%s@%d_%d" % (from_node_id, to_node_id, timestep, count) ac = Color.from_html_hash(arrow_color) packet = czml.CZMLPacket(id=id_txt, availability=availability) polyline = czml.Polyline( followSurface=False, positions={ "cartographicDegrees": [ from_node["NodeAttributes"]["Longitude"], from_node["NodeAttributes"]["Latitude"], 0, # altitude to_node["NodeAttributes"]["Longitude"], to_node["NodeAttributes"]["Latitude"], 0 # altitude ] }, material={ "polylineArrow": { "color": { "epoch": self._timestep_to_iso(timestep), "rgba": [ 0, ac.r, ac.g, ac.b, 255, dur_seconds + 60 * 60 * 12, ac.r, ac.g, ac.b, 0 ] } } }, width=arrow_thickness_pixels) packet.polyline = polyline self.doc.packets.append(packet) count += 1 if self._verbose: print("CZMLWriter.add_vector_migrations: %d migrations added." %\ count) return count
def _filter_users_criteria(filters): try: users = db.session.query(Users.userid, Users.userpos, func.length(Users.userpos), func.twAvg(func.speed(Users.userpos))).filter( *filters, ).all() except: traceback.print_exc() return jsonify({"errors": [DATA_UNINITIALIZED_ERROR]}), 400 # Import the library from czml import czml # Initialize a document doc = czml.CZML() # Create and append the document packet packet1 = czml.CZMLPacket(id='document', version='1.0') doc.packets.append(packet1) # Create and append a POINT packet packet3 = czml.CZMLPacket() for user_id, user, distance, speed in users: packet3.id = user_id pp = czml.Point() pp.color = {'rgba': [0, 255, 127, 55]} pp.outlineColor = {'rgba': [255, 0, 0, 128]} #varPos = czml.Position(cartographicDegrees=[2020-06-04T16:00:00Z,-56.189652081027,-34.8888227843656,0,2020-06-04T16:05:00Z,-56.189652081027,-34.8888227843656,0]) pos = czml.Position() #coords = ['2020-06-04T16:00:00Z','-56.189652081027','-34.8888227843656','0','2020-06-04T16:05:00Z','-56.189652081027','-34.8888227843656','0'] coords = serialize_trajectory(user) pos.epoch = coords['epoch'] pos.cartographicDegrees = coords['cartographicDegrees'] #varPos.cartographicDegrees = [2020-06-04T16:00:00Z,-56.189652081027,-34.8888227843656,0,2020-06-04T16:05:00Z,-56.189652081027,-34.8888227843656,0] #trayectoria = Path(pos,pp) packet3.position = pos packet3.point = pp #Path(pos, pp) #packet3.path = trayectoria #pp.Position = Position(varPos) doc.packets.append(packet3) # Write the CZML document to a file filename = "example.czml" doc.write(filename) return jsonify({ "users": [{ "id": user_id, "trajectory": serialize_trajectory(user), "distance": distance, "speed": speed, } for user_id, user, distance, speed in users] })
def testCone(self): # Create a new cone sc = czml.SolidColor(color={'rgba': [0, 255, 127, 55]}) mat = czml.Material(solidColor=sc) c = czml.Cone( show=True, innerMaterial=mat, outerMaterial=mat, capMaterial=mat, showIntersection=True, outerHalfAngle=1, innerHalfAngle=2.0, ) self.assertEqual( c.data(), { 'outerHalfAngle': 1, 'innerHalfAngle': 2.0, 'outerMaterial': { 'solidColor': { 'color': { 'rgba': [0, 255, 127, 55] } } }, 'show': True, 'showIntersection': True, 'capMaterial': { 'solidColor': { 'color': { 'rgba': [0, 255, 127, 55] } } }, 'innerMaterial': { 'solidColor': { 'color': { 'rgba': [0, 255, 127, 55] } } } }) # Create a new cone from an existing cone c2 = czml.Cone() c2.loads(c.dumps()) self.assertEqual(c2.data(), c.data()) # Verify passing in an unknown value raises a ValueError with self.assertRaises(ValueError): c3 = czml.Cone(bad_data=None) # Add a cone to a CZML packet packet = czml.CZMLPacket(id='abc') packet.cone = c2 self.assertEqual( packet.data(), { 'id': 'abc', 'cone': { 'outerHalfAngle': 1, 'innerHalfAngle': 2.0, 'outerMaterial': { 'solidColor': { 'color': { 'rgba': [0, 255, 127, 55] } } }, 'show': True, 'showIntersection': True, 'capMaterial': { 'solidColor': { 'color': { 'rgba': [0, 255, 127, 55] } } }, 'innerMaterial': { 'solidColor': { 'color': { 'rgba': [0, 255, 127, 55] } } } }, })