def _getPathsDetails(assignments): """ Given an Assignments dataframe, this script deconstruct it into a list of assignments(or called subAssignments) each subAssignment will have: the same odID; same type of movement(stationary/vertical/move) Parameters ---------- assignments: :ref:`Assignments`, Required The Assignments dataframe to be deconstructed into lists Returns ------- path: Path dataframe A list of description of each subAssignment lstSubAssignments: list of :ref:`Assignments` A list of Assignments dataframe each with the same odID """ # Icon list modelWithDuplicates = assignments['modelFile'].tolist() uniqueIconList = list(dict.fromkeys(modelWithDuplicates)) # Get path list from assignments dataframe lstSubAssignments = deconstructAssignments(assignments=assignments, includeStationaryFlag=True, includeVerticalFlag=True) # Now we prepare for .czml, the following is a Path Dataframe, which has the same length as lstSubAssignments path = pd.DataFrame(columns=['odID', 'czmlID', 'objectID', 'modelFile', 'action', 'modelScale', 'modelMinPxSize', 'startTimeSec', 'endTimeSec', 'intervalStart', 'intervalEnd', 'indexInlstShapepoints']) for i in range(len(lstSubAssignments)): path = path.append({ 'odID': lstSubAssignments[i].iloc[0]['odID'], 'czmlID': 'o-%s-%s-%s' % (lstSubAssignments[i].iloc[0]['objectID'].replace("'", r""), lstSubAssignments[i].iloc[0]['modelFile'], _getAction(lstSubAssignments[i])), 'objectID': lstSubAssignments[i].iloc[0]['objectID'], 'modelFile': lstSubAssignments[i].iloc[0]['modelFile'], 'action': _getAction(lstSubAssignments[i]), 'modelScale': lstSubAssignments[i].iloc[0]['modelScale'], 'modelMinPxSize': lstSubAssignments[i].iloc[0]['modelMinPxSize'], 'startTimeSec': lstSubAssignments[i].iloc[0]['startTimeSec'], 'endTimeSec': lstSubAssignments[i].iloc[-1]['endTimeSec'], 'intervalStart': "", 'intervalEnd': "", 'indexInlstShapepoints': i }, ignore_index=True) path.sort_values('odID', ascending=True) return [path, lstSubAssignments]
def createCesium(assignments=None, nodes=None, startDate=None, startTime='08:00:00', postBuffer=30, cesiumDir=None, problemDir=None, nodeColor=None, nodeStyle=None, pathColor=None, pathWeight=None, pathStyle=None, pathOpacity=None): """ This function generates several files required to view a solution in Cesium. The function requires assignments and/or nodes dataframes as input. Parameters ---------- assignments: :ref:`Assignments`, Conditional, `assignments` and `nodes` can not be None at the same time An :ref:`Assignments` dataframe describing vehicle movement over time. The assignments will be displayed as routes/paths in Cesium. If a 3D model is defined in the `modelFile` column of the assignments dataframe, this object will also be displayed. nodes: :ref:`Nodes`, Conditional, `assignments` and `nodes` can not be None at the same time A :ref:`Nodes` dataframe describing the locations of nodes. These nodes will be displayed on the map in Cesium. startDate: string, Optional, format is "YYYY-MM-DD", default as today Defines the start date to be displayed in Cesium. startTime: string, Optional, format is "HH:MM:SS", default as '08:00:00' Defines the time at which the Cesium video begins, on the start date. postBuffer: int, Optional, default as 30 Specifies the additional time (in seconds) that the Cesium video will continue to run after the last assignment is completed. cesiumDir: string, Required, default as None This should be the full absolute path to the directory where Cesium is installed. For example, for Windows it might be "D:/Cesium"; for Linux it might be "/home/user/Cesium". problemDir: string, Required, default as None The path name of the generated problem directory. This path is relative to the root of Cesium. For example, if `cesiumDir = '/home/user/Cesium'` and `problemDir = 'veroviz/problems/TSP'` then the files will be generated in the directory `'/home/user/Cesium/veroviz/problems/TSP'`. nodeColor: string, Optional, default as None Overrides the `cesiumColor` column of the input `nodes` dataframe. This will define the color of all nodes displayed in Cesium. See :ref:`Cesium Style` for the collection of available colors. nodeStyle: string, Optional, default as None Overrides the `cesiumIconType` column of the input `nodes` dataframe. Currently, the only option is 'pin'. pathColor: string, Optional, default as None Overrides the `cesiumColor` column of the input `assignments` dataframe. This will define the color of all arcs displayed in Cesium. See :ref:`Cesium Style` for the collection of available colors. pathWeight: int, Optional, default as None Overrides the `cesiumWeight` column of the input `assignments` dataframe. This will define the weight (in pixels) of all arcs displayed in Cesium. See :ref:`Cesium Style` for more information. pathStyle: string, Optional, default as None Overrides the `cesiumStyle` column of the input `assignments` dataframe. This will define the style of all arcs displayed in Cesium. See :ref:`Cesium Style` for available options. pathOpacity: float in [0, 1], Optional, default as None Overrides the `cesiumOpacity` column of the input `assignments` dataframe. This will define the opacity of all arcs displayed in Cesium. See :ref:`Cesium Style` for more information. Return ------ N/A Note ---- This function generates the following files within the directory specified by input argument `problemDir`: - [problemDir].vrv (where [problemDir] is replaced by the value of `problemDir`); - config.js - displayNodes.js - displayPath.js - routes.czml Instructions for starting Cesium are provided at https://veroviz.org/documentation.html Example -------- Import veroviz and check the latest version. >>> import veroviz as vrv >>> import os >>> vrv.checkVersion() Create two nodes. >>> myNodes = vrv.createNodesFromLocs( ... locs = [[42.1538, -78.4253], ... [42.6343, -78.1146]]) >>> myNodes Move the truck from one node to the other. >>> myAssignments = vrv.getShapepoints2D( ... odID = 0, ... objectID = 'truck', ... modelFile = 'veroviz/models/ub_truck.gltf', ... modelScale = 80, ... modelMinPxSize = 20, ... startLoc = list(myNodes.loc[0][['lat', 'lon']].values), ... endLoc = list(myNodes.loc[1][['lat', 'lon']].values), ... routeType = 'euclidean2D', ... dataProvider = None, ... speedMPS = vrv.convertSpeed(55, 'miles', 'hr', 'm', 's')) Create Cesium output. >>> vrv.createCesium( ... assignments = myAssignments, ... nodes = myNodes, ... startTime = '08:00:00', ... cesiumDir = os.environ['CESIUMDIR'], ... problemDir = 'createCesium_example') """ # validation [valFlag, errorMsg, warningMsg] = valCreateCesium(assignments, nodes, startDate, startTime, postBuffer, cesiumDir, problemDir, nodeColor, pathColor, pathWeight, pathStyle, pathOpacity) if (not valFlag): print(errorMsg) return elif (VRV_SETTING_SHOWWARNINGMESSAGE and warningMsg != ""): print(warningMsg) # Set default start date as today if (startDate is None): startDate = datetime.date.today() # Some modification about slashes: # cesiumDir - no tail slash # problemDir - no head slash and no tail slash # Change all backslash to slash cesiumDir = delTailSlash(cesiumDir) problemDir = delTailSlash(problemDir) problemDir = delHeadSlash(problemDir) cesiumDir = replaceBackslashToSlash(cesiumDir) problemDir = replaceBackslashToSlash(problemDir) # In case the problemDir does not exist fullDir = '%s/%s' % (cesiumDir, problemDir) if not os.path.exists(fullDir): os.makedirs(fullDir, exist_ok=True) # Mission duration, from time zero to endtime+postBuffer availStart = _getCesiumTime(startDate, startTime, 0) availEnd = _getCesiumTime(startDate, startTime, (max(assignments['endTimeSec']) + postBuffer)) # Decode Assignments dataframe to a Path dataframe (with details of a path) and a list of Assignments dataframes, and generate .js and .czml files [path, lstSubAssignments] = _getPathsDetails(assignments) lstNonStationarySubAssignments = deconstructAssignments( assignments=assignments, includeVerticalFlag=True) # Update 'intervalStart' and 'intervalEnd' to cesiumTime for i in path.index: path.at[i, 'intervalStart'] = _getCesiumTime(startDate, startTime, path.at[i, 'startTimeSec']) path.at[i, 'intervalEnd'] = _getCesiumTime( startDate, startTime, path.at[i, 'endTimeSec']) if ( path.at[i, 'endTimeSec'] >= 0) else availEnd path.drop(columns=['startTimeSec', 'endTimeSec']) # Write problem selector _writeSelector(fullDir, problemDir) # Write Configs mapBoundary = getMapBoundary(nodes=nodes, arcs=assignments, locs=None) _writeConfigs(mapBoundary, availStart, path, fullDir, problemDir) # Write Nodes if (nodes is not None): _writeNodes(nodes, nodeColor, fullDir) # Write Assignments if (len(path) > 0): _writeAssignmentsJS(lstNonStationarySubAssignments, pathColor, pathWeight, pathStyle, pathOpacity, fullDir) _writeAssignmentsCZML(path, lstSubAssignments, availStart, availEnd, fullDir) return