Tile rendering method and apparatus
By shifting symbolization and vertex construction from the main thread to a sub-thread, the problem of UI lag caused by excessive computational load on the main thread during map rendering is solved, resulting in smoother rendering.
Patent Information
- Application Number
- CN202611398977.2
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Filing Date
- 2026-09-09
- Publication Date
- 2026-11-06
AI Technical Summary
In existing technologies, the main thread's computational load is too heavy during map rendering, causing the interface to lag.
The symbolization and vertex construction are moved from the main thread to a child thread. The main thread initiates the tile loading task, while the child thread completes the symbolization and vertex construction, generates vertex buffer data and texture data, and sends this data back to the main thread. The main thread only performs rendering object creation and scene mounting.
It significantly reduces the computational load on the main thread, avoids UI lag, and improves the smoothness of map rendering and user experience.
Smart Images

Figure CN123048093A_ABST
Abstract
Description
Technical Field
[0001] This application relates to the field of map technology, and in particular to a tile rendering method and apparatus. Background Technology
[0002] In Web Geographic Information System (WebGIS) applications, the rendering performance of map data directly impacts the user experience. To achieve efficient rendering, map data typically needs to be transmitted from the server to the front end in a compact and scalable format, and vector tiles are currently a widely adopted data transmission format in the WebGIS field.
[0003] Currently, the main thread initiates tile loading tasks to child threads. The child threads receive these tasks, parse the Protocol Buffer Binary Format (PBF) data, and send the parsing results back to the main thread. Based on the parsing results from the child threads and the tile loading tasks, the main thread loads resources, constructs vertex data, and then performs tile rendering.
[0004] However, existing technologies suffer from a technical problem where the main thread's computational load is too heavy during map rendering, leading to interface lag. Summary of the Invention
[0005] This application provides a tile rendering method and apparatus to solve the technical problem of interface lag caused by excessive main thread computational load during map rendering in the prior art.
[0006] In a first aspect, embodiments of this application provide a tile rendering method applied to an electronic device with a main thread and child threads deployed, the method comprising:
[0007] The main thread sends a tile loading task to the child thread, and the tile loading task carries an identifier of the target tile that needs to be loaded based on the current viewport.
[0008] The sub-thread responds to the tile loading task and obtains the vector feature data corresponding to the tile loading task;
[0009] The sub-thread performs symbolization processing on the vector feature data to generate a builder object for describing the rendering style;
[0010] The sub-thread constructs vertices based on the builder object, generating vertex buffer data and texture data;
[0011] The sub-thread sends the vertex buffer data and the texture data to the main thread;
[0012] The main thread creates a rendering object based on the received vertex buffer data and texture data, and adds the rendering object to the rendering scene.
[0013] In one possible implementation, the sub-thread performs symbolic processing on the vector feature data to generate a builder object for describing the rendering style, including:
[0014] The sub-thread calls the renderer's symbol construction method according to the renderer configuration corresponding to the layer to which the vector feature data belongs;
[0015] The symbol construction method is used to convert the vector feature data into multiple builder objects;
[0016] Each builder object contains the type of the builder object, a list of feature data, and rendering style parameters.
[0017] In one possible implementation, the sub-thread constructs vertices based on the builder object, generating vertex buffer data and texture data, including:
[0018] The sub-thread generates the texture data based on the resource data required by the builder object;
[0019] For each builder object, vertex attribute data is generated based on the texture data and written to the vertex buffer.
[0020] Group the builder objects written to the vertex buffer by layer name to obtain multiple builder object groups;
[0021] Each builder object group contains at least one builder object and a corresponding vertex buffer, wherein the vertex buffer data includes each builder object in the plurality of builder object groups and the corresponding vertex buffer.
[0022] In one possible implementation, the main thread creates a rendering object based on the received vertex buffer data and texture data, and adds the rendering object to the rendering scene, including:
[0023] The main thread creates a texture object for the texture data;
[0024] A rendering object is created based on the vertex buffer data and the texture object, the rendering object containing geometry and materials;
[0025] Add the rendered object to the corresponding layer of the rendered scene.
[0026] In one possible implementation, the main thread sends a tile loading task to the child thread, including:
[0027] If the tile loading task carries the identifier of the target sub-thread, the main thread determines whether the number of tasks of the target sub-thread is less than the preset task quantity limit;
[0028] If the value is less than the target value, the tile loading task will be distributed to the target sub-thread.
[0029] If the value is greater than or equal to the value, the tile loading task is added to the first queue.
[0030] If the tile loading task does not carry the identifier of the target sub-thread, then the tile loading task is added to the second queue;
[0031] The scheduling priority of the first queue is higher than that of the second queue, and the tile loading tasks corresponding to the same data source all carry the same target sub-thread identifier.
[0032] In one possible implementation, the sub-thread constructs vertices based on the builder object, generating vertex buffer data and texture data, including:
[0033] The sub-thread sends resource requests to the main thread in parallel via reverse communication. The resource requests include at least one of image resource requests, glyph resource requests, and SVG resource requests.
[0034] The main thread responds to the resource request sent by the child thread, calls the corresponding resource manager in parallel to load the resource, and sends the loaded resource data back to the child thread;
[0035] After obtaining all the resource data corresponding to the resource request, the sub-thread constructs vertices based on the builder object, generating vertex buffer data and texture data.
[0036] In one possible implementation, after the sub-thread performs symbolization processing on the vector feature data to generate a builder object for describing the rendering style, the method further includes:
[0037] The sub-thread quantizes the coordinates of point features in the builder object to a preset precision and generates a position key;
[0038] If there are other point elements at the position corresponding to the position key, the point element is offset along the preset axis direction, and the offset amount is recorded.
[0039] Based on the offset, the corresponding point features in other builder objects associated with the point feature are offset along the preset axis direction.
[0040] In one possible implementation, after the sub-thread responds to the tile loading task and obtains the vector feature data corresponding to the tile loading task, the method further includes:
[0041] For point features with the tile restriction option enabled, the sub-thread determines whether the coordinates of the point feature are within the latitude and longitude range of the target tile; wherein, the tile restriction option is used to mark point features that need to perform tile boundary filtering;
[0042] If not, then remove the point feature from the vector feature data.
[0043] Secondly, embodiments of this application provide a tile rendering apparatus, applied to an electronic device with a main thread and sub-threads deployed, the apparatus comprising:
[0044] The sending module is used to send a tile loading task to the child thread through the main thread. The tile loading task carries an identifier of the target tile that needs to be loaded based on the current viewport.
[0045] The acquisition module is used to acquire vector feature data corresponding to the tile loading task in response to the tile loading task via the sub-thread;
[0046] The processing module is used to perform symbolization processing on the vector feature data through the sub-thread to generate a builder object for describing the rendering style;
[0047] The construction module is used to construct vertices based on the builder object through the sub-thread, and generate vertex buffer data and texture data;
[0048] The sending module is further configured to send the vertex buffer data and the texture data to the main thread through the sub-thread;
[0049] A creation module is used to create a rendering object based on the received vertex buffer data and texture data through the main thread, and add the rendering object to the rendering scene.
[0050] In one possible implementation, the processing module is specifically used for:
[0051] The sub-thread calls the renderer's symbol construction method according to the renderer configuration corresponding to the layer to which the vector feature data belongs;
[0052] The symbol construction method is used to convert the vector feature data into multiple builder objects;
[0053] Each builder object contains the type of the builder object, a list of feature data, and rendering style parameters.
[0054] In one possible implementation, the building module is specifically used for:
[0055] The sub-thread generates the texture data based on the resource data required by the builder object;
[0056] For each builder object, vertex attribute data is generated based on the texture data and written to the vertex buffer.
[0057] Group the builder objects written to the vertex buffer by layer name to obtain multiple builder object groups;
[0058] Each builder object group contains at least one builder object and a corresponding vertex buffer, wherein the vertex buffer data includes each builder object in the plurality of builder object groups and the corresponding vertex buffer.
[0059] In one possible implementation, the creation module is specifically used for:
[0060] The main thread creates a texture object for the texture data;
[0061] A rendering object is created based on the vertex buffer data and the texture object, the rendering object containing geometry and materials;
[0062] Add the rendered object to the corresponding layer of the rendered scene.
[0063] In one possible implementation, the sending module is specifically used for:
[0064] If the tile loading task carries the identifier of the target sub-thread, the main thread determines whether the number of tasks of the target sub-thread is less than the preset task quantity limit;
[0065] If the value is less than the target value, the tile loading task will be distributed to the target sub-thread.
[0066] If the value is greater than or equal to the value, the tile loading task is added to the first queue.
[0067] If the tile loading task does not carry the identifier of the target sub-thread, then the tile loading task is added to the second queue;
[0068] The scheduling priority of the first queue is higher than that of the second queue, and the tile loading tasks corresponding to the same data source all carry the same target sub-thread identifier.
[0069] In one possible implementation, the building module is specifically used for:
[0070] The sub-thread sends resource requests to the main thread in parallel via reverse communication. The resource requests include at least one of image resource requests, glyph resource requests, and SVG resource requests.
[0071] The main thread responds to the resource request sent by the child thread, calls the corresponding resource manager in parallel to load the resource, and sends the loaded resource data back to the child thread;
[0072] After obtaining all the resource data corresponding to the resource request, the sub-thread constructs vertices based on the builder object, generating vertex buffer data and texture data.
[0073] In one possible implementation, the tile rendering apparatus further includes an offset module, which, after the sub-thread performs symbolic processing on the vector feature data to generate a builder object describing the rendering style, is used to:
[0074] The sub-thread quantizes the coordinates of point features in the builder object to a preset precision and generates a position key;
[0075] If there are other point elements at the position corresponding to the position key, the point element is offset along the preset axis direction, and the offset amount is recorded.
[0076] Based on the offset, the corresponding point features in other builder objects associated with the point feature are offset along the preset axis direction.
[0077] In one possible implementation, after the sub-thread responds to the tile loading task and obtains the vector feature data corresponding to the tile loading task, the processing module is further configured to:
[0078] For point features with the tile restriction option enabled, the sub-thread determines whether the coordinates of the point feature are within the latitude and longitude range of the target tile; wherein, the tile restriction option is used to mark point features that need to perform tile boundary filtering;
[0079] If not, then remove the point feature from the vector feature data.
[0080] Thirdly, embodiments of this application provide an electronic device, including: a memory and a processor;
[0081] The memory stores computer-executed instructions;
[0082] The processor executes computer execution instructions stored in the memory, causing the processor to perform the implementation method described in the first aspect above.
[0083] Fourthly, embodiments of this application provide a computer-readable storage medium storing computer-executable instructions, which, when executed by a processor, are used to implement the embodiments described in the first aspect above.
[0084] Fifthly, embodiments of this application provide a computer program product, including a computer program that, when executed by a processor, implements the implementation methods described in the first aspect above.
[0085] The tile rendering method and apparatus provided in this application significantly reduce the computational load of the main thread by transferring computationally intensive tasks such as symbolization and vertex construction from the main thread to the sub-thread. The main thread only needs to complete the creation of rendering objects and scene mounting, thus avoiding interface lag caused by the main thread's inability to respond to user interactions in a timely manner due to performing time-consuming operations, and improving the smoothness of map rendering and user experience. Attached Figure Description
[0086] The accompanying drawings, which are incorporated in and form part of this specification, illustrate embodiments consistent with this application and, together with the description, serve to explain the principles of this application.
[0087] Figure 1 A flowchart illustrating the tile rendering method provided by existing technology;
[0088] Figure 2 A flowchart illustrating the tile rendering method provided in this application embodiment. Figure 1 ;
[0089] Figure 3 A flowchart illustrating the tile rendering method provided in this application embodiment. Figure 2 ;
[0090] Figure 4 A flowchart illustrating the tile rendering method provided in this application embodiment. Figure 3 ;
[0091] Figure 5 A flowchart illustrating the tile rendering method provided in this application embodiment. Figure 4 ;
[0092] Figure 6 A flowchart illustrating the tile rendering method provided in this application embodiment. Figure 5 ;
[0093] Figure 7 A flowchart illustrating the tile rendering method provided in this application embodiment. Figure 6 ;
[0094] Figure 8 A flowchart illustrating the tile rendering method provided in this application embodiment. Figure 7;
[0095] Figure 9 This is a schematic diagram of the data flow of the tile rendering method provided in the embodiments of this application;
[0096] Figure 10 This is a schematic diagram of the structure of the tile rendering device provided in the embodiments of this application;
[0097] Figure 11 This is a schematic diagram of the structure of an electronic device provided in an embodiment of this application.
[0098] The accompanying drawings illustrate specific embodiments of this application, which will be described in more detail below. These drawings and descriptions are not intended to limit the scope of the concept in any way, but rather to illustrate the concept of this application to those skilled in the art through reference to particular embodiments. Detailed Implementation
[0099] Exemplary embodiments will now be described in detail, examples of which are illustrated in the accompanying drawings. When the following description relates to the drawings, unless otherwise indicated, the same numbers in different drawings denote the same or similar elements. The embodiments described in the following exemplary embodiments do not represent all embodiments consistent with this application. Rather, they are merely examples of apparatuses and methods consistent with some aspects of this application.
[0100] It should be noted that the user information (including but not limited to user device information, user personal information, etc.) and data (including but not limited to data used for analysis, data stored, data displayed, etc.) involved in this application are all information and data authorized by the user or fully authorized by all parties. Furthermore, the collection, use and processing of the relevant data must comply with relevant laws, regulations and standards, and corresponding operation entry points are provided for users to choose to authorize or refuse.
[0101] First, the application scenarios involved in this application will be explained:
[0102] With the widespread adoption of mobile internet and location-based services, WebGIS applications have become infrastructure in fields such as smart cities, traffic navigation, and emergency command. In WebGIS applications, the rendering performance of map data directly impacts user experience. Current mainstream WebGIS front-end rendering technologies are based on Web Graphics Library (WebGL), using Graphics Processing Units (GPUs) to accelerate the visualization of massive amounts of geospatial data.
[0103] To achieve efficient rendering, map data typically needs to be transmitted from the server to the front end in a compact and scalable format, and vector tiles are the widely adopted data transmission format in the current WebGIS field. The Open Geospatial Consortium (OGC) released the vector tile coding specification (OGC 065r1) in 2017, defining the data structure and encoding method for vector tiles. Currently, most mainstream map services use this vector tile technology.
[0104] In existing technologies, the following methods are commonly used: Figure 1 The tile rendering process is shown. Figure 1 A flowchart illustrating the existing tile rendering method, such as... Figure 1 As shown, the main thread initiates a tile loading task to the child thread. The child thread receives the tile loading task, parses the PBF data, and sends the parsing result back to the main thread. Based on the parsing result sent back by the child thread and the tile loading task, the main thread loads resources, constructs vertex data, and then performs tile rendering.
[0105] In the rendering process described above, symbolization requires determining the rendering method of each element based on style rules, which are typically described in the form of style expressions. In existing solutions, both vector tile symbolization and vertex construction occur on the main thread. Specifically, style expressions need to be evaluated in real-time by the main thread based on the current zoom level, meaning symbolization can only be completed on the main thread. Some open-source implementations based on similar architectures also use similar approaches, where sub-threads are only responsible for data requests and PBF decoding, while resource loading, symbolization, and vertex construction are still all concentrated on the main thread. Meanwhile, the main thread also needs to handle JavaScript execution, Document Object Model (DOM) operations, Cascading Style Sheets (CSS) style calculations, and page rendering. When the main thread performs these time-consuming operations, it cannot respond promptly to user interactions such as dragging, zooming, and clicking, leading to UI stuttering. According to browser rendering mechanisms, the estimated time for a single frame is typically 16.67ms (corresponding to 60fps); once this time is exceeded, users will perceive stuttering.
[0106] The aforementioned architectural flaws become even more apparent in practical applications. Actual test data shows that when a single tile contains 5000 features, symbolization takes approximately 20-50ms, vertex construction takes approximately 30-150ms, totaling 50-200ms, far exceeding the budgeted time for a single frame. This causes the main thread's frame rate to drop from 60fps to below 15fps. During continuous scaling operations, each frame needs to process multiple tiles, further exacerbating the stuttering.
[0107] In summary, existing technologies suffer from the technical problem of excessive computational load on the main thread during map rendering, leading to UI lag.
[0108] Based on the aforementioned technical problems, the technical concept of this application is as follows: During the research of WebGIS vector tile rendering methods, the inventors discovered that in existing technologies, symbolization processing and vertex construction are both executed on the main thread. However, the main thread also needs to handle user interaction and page rendering simultaneously, leading to excessive computational load and interface lag. The inventors further discovered that sub-threads are currently only used for data requests and PBF decoding, and computational resources are not being fully utilized. Therefore, the inventors considered migrating symbolization processing and vertex construction from the main thread to a sub-thread: the main thread only initiates the tile loading task, and after obtaining the corresponding vector feature data, the sub-thread completes symbolization processing within the sub-thread to generate a builder object. Then, based on the builder object, vertex construction is performed, generating vertex buffer data and texture data, which are then sent back to the main thread. The main thread only needs to create rendering objects based on the received vertex buffer data and texture data and add them to the rendering scene. In this way, the main thread no longer performs time-consuming operations such as symbolization processing and vertex construction, significantly reducing the computational load, thereby avoiding main thread blocking and improving the smoothness of map rendering.
[0109] The technical solution of this application and how the technical solution of this application solves the above-mentioned technical problems are described in detail below with specific embodiments. These specific embodiments can be combined with each other, and the same or similar concepts or processes may not be described again in some embodiments. The embodiments of this application will now be described with reference to the accompanying drawings.
[0110] Figure 2 A flowchart illustrating the tile rendering method provided in this application embodiment. Figure 1 ,like Figure 2 As shown, the method includes:
[0111] S21. The main thread sends a tile loading task to the child thread.
[0112] The execution subject of this application embodiment is an electronic device, which can be a terminal device, such as a laptop, desktop computer, or tablet computer, or a server. In practical applications, whether the electronic device is a terminal device or a server can be determined according to the actual situation, and no specific limitation is imposed on it.
[0113] The electronic device has a main thread and a sub-thread.
[0114] Specifically, the main thread is the core execution thread in an electronic device used to handle user interaction, page rendering, and scheduling other threads to perform tasks. It is usually provided by the browser's main execution environment.
[0115] Child threads are independent execution threads created by the main thread and running in the background, such as worker threads created in a browser. These child threads process tile loading tasks in parallel to share the computational tasks of the main thread and prevent the main thread from being unable to respond to user interactions in a timely manner due to performing time-consuming operations.
[0116] The tile loading task carries an identifier of the target tile that needs to be loaded based on the current viewport. The identifier of the target tile is used to uniquely identify the target tile that needs to be loaded.
[0117] In practical applications, the identifier of a target tile can be determined by its row and column numbers and the zoom level. The current viewport refers to the map area currently visible to the user on the screen. The main thread calculates the identifiers of all tiles intersecting with the current viewport based on the geographical scope of the current viewport and the current zoom level, and uses these tiles as the target tiles to be loaded.
[0118] For example, when a user zooms in on the map to a certain level, the current viewport may cover multiple tiles. The main thread can calculate the identifiers of these tiles according to the tile division rules, and thus generate the corresponding tile loading task.
[0119] In practical applications, when the main thread sends tile loading tasks to child threads, a thread pool can be used for unified scheduling. Specifically, the thread pool maintains multiple child threads. The main thread puts the tile loading task into the thread pool, and the thread pool distributes the task to the appropriate child thread for execution according to the scheduling strategy.
[0120] The thread pool can distribute tasks to the corresponding child threads in the following two possible ways.
[0121] In one possible implementation, the thread pool can select one idle child thread for distribution in a round-robin or random manner.
[0122] In another possible implementation, if the tile loading task carries an identifier for the target sub-thread, the main thread determines whether the number of tasks for the target sub-thread is less than a preset task limit. If it is less, the tile loading task is distributed to the target sub-thread; if it is greater than or equal to the target sub-thread, the tile loading task is added to the first queue. If the tile loading task does not carry an identifier for the target sub-thread, the tile loading task is added to the second queue.
[0123] In this context, tile loading tasks corresponding to the same data source all carry the same target sub-thread identifier, allowing tile loading tasks from the same data source to be processed by the same sub-thread. A data source refers to the source that provides vector feature data, such as a vector data source or a vector tile data source.
[0124] The preset task limit is used to restrict the number of tasks that a single sub-thread can execute simultaneously, thus preventing a single sub-thread from experiencing performance degradation due to too many concurrent tasks. For example, the preset task limit can be 1, 2, 3, etc., and it can be preset based on empirical or experimental values. This application embodiment does not impose specific restrictions on this.
[0125] The first queue is a waiting queue for tile loading tasks that carry a target sub-thread identifier but whose number of target sub-thread tasks has reached or exceeded the preset task limit. The second queue is a waiting queue for tile loading tasks that do not carry a target sub-thread identifier. The scheduling priority of the first queue is higher than that of the second queue.
[0126] During actual scheduling, the thread pool first retrieves tile loading tasks from the first queue and checks if the number of tasks for the corresponding target child thread is less than the preset task limit. If so, the task is immediately dispatched to the target child thread for execution. If not, the tile loading task is kept in the first queue, and the thread pool continues processing the next task in the first queue. When the tasks in the first queue are completed or none of the tasks in the first queue can be dispatched immediately, the thread pool then retrieves tile loading tasks from the second queue and dispatches them to idle child threads for execution.
[0127] In this way, by distinguishing between the first queue and the second queue, it can be ensured that tasks carrying the target sub-thread identifier can be scheduled first, so that tile loading tasks from the same data source are handled by the same sub-thread, achieving thread affinity, and further reusing the data source state already cached in the sub-thread, thereby improving processing efficiency.
[0128] It is understandable that the cached data source state of the child thread can include information such as the feature data, spatial extent, and layer configuration of the data source.
[0129] S22. The sub-thread responds to the tile loading task and obtains the vector feature data corresponding to the tile loading task.
[0130] Vector feature data refers to a set of data used to describe the geometric and attribute information of map features, including at least one of point features, line features, and polygon features. Each feature carries corresponding coordinate data and attribute data. The attribute data is used to describe additional information about the feature, such as name, type, color, and width.
[0131] For example, point features can represent points of interest, line features can represent roads, and polygon features can represent buildings or water bodies.
[0132] In one possible implementation, for a vector data source, the sub-thread searches for the vector feature data corresponding to the target tile's identifier from its cached data source state, based on the identifier of the target tile carried in the tile loading task. If the corresponding vector feature data exists in the cached data source state, it is read directly, avoiding duplicate requests and parsing.
[0133] In another possible implementation, for a vector tile data source, a sub-thread receives a tile data packet sent by the main thread that corresponds to the identifier of the target tile, and decodes the tile data packet to obtain vector feature data. The tile data packet can be in binary format, such as PBF.
[0134] In practical applications, the sub-thread can combine the two methods described above for data acquisition. Specifically, the sub-thread first searches for the target tile's identifier in the cached data source state. If no match is found, it receives the tile data packet sent by the main thread, decodes it, and writes the decoded vector feature data into the sub-thread's cached data source state for reuse in subsequent tile loading tasks. In this way, the sub-thread can accurately obtain the corresponding vector feature data according to the tile loading task, providing data support for subsequent symbolization processing and vertex construction.
[0135] S23. The sub-thread performs symbolization processing on the vector feature data and generates a builder object to describe the rendering style.
[0136] In one possible implementation, the child thread first calls the renderer's symbol construction method based on the renderer configuration corresponding to the layer to which the vector feature data belongs. Then, the symbol construction method converts the vector feature data into multiple builder objects.
[0137] In this context, a layer refers to a collection of features in a map, divided according to business or data characteristics, such as road layers, building layers, and water feature layers. In practical applications, each layer typically has independent rendering rules; for example, road layers are rendered using solid lines, while water feature layers are filled with blue. The renderer configuration for each layer defines the type of renderer to be used and the relevant rendering parameters.
[0138] A renderer configuration is a set of rules or parameters that guide the symbolization process. It includes the renderer type, the definition of data-driven style expressions, and default style values. When a sub-thread performs symbolization on vector feature data of a specific layer, it reads the renderer configuration corresponding to that layer and calls the appropriate renderer based on that configuration.
[0139] Symbol construction methods are provided by the renderer and are processing functions used to convert vector feature data into builder objects. Different renderers may correspond to different symbol construction methods or the same symbol construction method, which can be determined according to the actual situation. This application embodiment does not impose specific restrictions on this. By calling the renderer's symbol construction method, a sub-thread can convert vector feature data belonging to the same layer and meeting specific conditions into one or more builder objects.
[0140] Each builder object contains the type of the builder object, a list of feature data, and rendering style parameters.
[0141] The types of builder objects include point builder, line builder, face builder, and text builder, among others.
[0142] A feature data list is a collection of vector feature data recorded in a builder object. Features contained in the feature data list of the same builder object are rendered using the same or similar rendering style parameters. For example, all points of interest using the same icon style can be placed in the feature data list of the same point type builder.
[0143] Rendering style parameters specify the specific style information used when rendering features in the builder object. These parameters can include at least one of the following: color, line weight, icon, text font, text size, offset, and rotation angle. It's important to understand that the specific values of these rendering style parameters can be determined jointly based on the renderer configuration of the layer and the attribute data of the vector feature data.
[0144] In the above method, symbolization processing based on the renderer configuration corresponding to the layer can accurately and efficiently convert vector feature data into a well-structured builder object, providing a reliable style description and feature organization method for subsequent vertex construction, ensuring the standardization and consistency of the symbolization process, which is conducive to parallel and batch processing of vector feature data of different layers in sub-threads, further improving the efficiency of symbolization processing in sub-threads, and ensuring that the final rendering result conforms to the rendering rules preset by the layer.
[0145] S24. The child thread constructs vertices based on the builder object, generating vertex buffer data and texture data.
[0146] In one possible implementation, the sub-thread first generates texture data based on the resource data required by the builder object. Then, for the feature data corresponding to each builder object, vertex attribute data is generated based on the texture data and written to the vertex buffer. Finally, the builder objects written to the vertex buffer are grouped by layer name, resulting in multiple builder object groups.
[0147] The resource data includes at least one of icon image data, font data, and vector graphics data. In practical applications, the resource data required by the builder object can be pre-loaded by the main thread through the resource manager and passed back to the child thread, or it can be read by the child thread from its own cache. The specific method of obtaining resource data will be explained in subsequent embodiments and will not be repeated here.
[0148] The specific form of resource data can be determined based on the type of the builder object and rendering requirements. For example, a point builder needs icon image data, a text builder needs glyph data, and a line builder needs dashed line texture image data.
[0149] The texture data includes one or more texture atlases, each containing at least one image region generated from the resource data.
[0150] Vertex attribute data describes the position, color, texture coordinates, normals, and other attributes of a single vertex. A vertex buffer is a contiguous memory area used to store vertex attribute data; it can be implemented using a structured floating-point array, with the attribute data for each vertex arranged in a fixed order. In practical applications, the graphics processor can directly read vertex attribute data from the vertex buffer without any additional conversion.
[0151] A builder object group refers to a data set formed by grouping at least one builder object belonging to the same layer and its corresponding vertex buffer according to the layer name. Vertex buffer data includes each builder object in multiple builder object groups and its corresponding vertex buffer. It can be understood that builder objects in a builder object group belong to the same layer and can share the same rendering order and rendering state.
[0152] In this implementation, texture generation, vertex attribute generation, and layer grouping are all completed in a sub-thread. This allows the sub-thread to directly produce structured texture data and vertex buffer data that can be directly used by the main thread and the graphics processor, reducing subsequent processing steps in the main thread, ensuring the matching of vertex data and texture data, and improving the efficiency of rendering object creation. At the same time, grouping by layer name facilitates rendering management by the main thread by layer, further improving rendering performance.
[0153] Optionally, builder objects with empty vertex buffers can be filtered out before grouping the builder objects written to the vertex buffers by layer name.
[0154] S25. The child thread sends the vertex buffer data and texture data to the main thread.
[0155] After the child thread completes vertex construction, it needs to send the generated vertex buffer data and texture data to the main thread so that the main thread can create rendering objects and complete rendering based on this data.
[0156] In practical applications, child threads and the main thread can send data via message passing. Child threads can encapsulate vertex buffer data and texture data into messages and send them to the main thread through a message interface. For binary data within the vertex buffer, the child thread can also use transferable objects to directly transfer ownership of the data. The main thread can then receive and use the data directly without needing to copy it, thus improving data transfer efficiency.
[0157] S26. The main thread creates a rendering object based on the received vertex buffer data and texture data, and adds the rendering object to the rendering scene.
[0158] The rendering object is the basic renderable unit in the rendering scene, containing geometry and materials, so that the graphics processor can perform drawing operations based on the rendering object.
[0159] Geometry is the part of a rendering object used to describe vertex data. The main thread creates geometry based on vertex buffer data sent by the child thread, enabling the graphics processor to determine the shape and position of the primitives to be drawn based on the vertex data in the geometry.
[0160] Material is the part of a rendering object that describes the surface appearance properties. It can include information such as shader program, texture object, color, transparency, and lighting parameters. The main thread creates materials based on texture objects so that the rendering object can correctly sample the texture object during drawing.
[0161] In one possible implementation, the main thread first creates a texture object for the texture data, then creates a render object based on the vertex buffer data and the texture object, and finally adds the render object to the corresponding layer of the rendering scene.
[0162] Texture objects are objects in the graphics processor used to store texture data. They can be configured with parameters such as texture filtering mode and texture coordinate wrapping mode, so that the texture can be displayed in the expected way during rendering.
[0163] The rendering scene is a tree structure used to organize and manage all rendering objects. It contains multiple layers, each layer holding a group of rendering objects with the same rendering order or rendering state. The main thread adds rendering objects to the corresponding layers of the rendering scene, allowing the rendering objects to be rendered sequentially according to the layer order, thus ensuring the correct occlusion relationships and overlay order between different layers in the map.
[0164] The main thread performs only lightweight operations such as texture object creation, render object assembly, and scene mounting. It fully utilizes the vertex buffer data and texture data already generated by the child threads, avoiding the main thread's involvement in time-consuming calculations such as vertex construction, thus significantly reducing the main thread's processing time per frame. Meanwhile, the render objects contain geometry and materials, enabling direct rendering by the graphics processor, ensuring the real-time performance and smoothness of map display, and further enhancing the stability of large-scale vector tile rendering.
[0165] Specifically, the main thread first uploads the texture data sent by the sub-thread to the graphics processor, generating a texture object and setting the texture filtering mode to linear filtering to ensure smooth texture sampling. Next, the main thread creates geometry using vertex buffer data. This geometry includes vertex attribute layouts describing the position, color, and texture coordinates of each vertex. Simultaneously, the main thread generates a material based on the previously created texture object. This material references the texture object as a sampling source during rendering and sets the corresponding shading parameters. Finally, the main thread combines the geometry and material into a rendering object and adds it to the corresponding layer node in the rendering scene, enabling it to participate in subsequent graphics processor rendering according to layer order.
[0166] The tile rendering method provided in this application is applied to an electronic device with a main thread and sub-threads. The main thread sends a tile loading task to the sub-threads, and the sub-threads respond to the tile loading task by obtaining the vector feature data corresponding to the task. The sub-threads perform symbolic processing on the vector feature data to generate a builder object describing the rendering style. Then, based on the builder object, they perform vertex construction, generating vertex buffer data and texture data, which are then sent to the main thread. The main thread creates a rendering object based on the received vertex buffer data and texture data and adds the rendering object to the rendering scene. The tile loading task carries an identifier of the target tile to be loaded based on the current viewport. In this technical solution, by transferring computationally intensive tasks such as symbolic processing and vertex construction from the main thread to the sub-threads, the main thread only needs to complete the rendering object creation and scene mounting, significantly reducing the computational load on the main thread. This avoids interface lag caused by the main thread's inability to respond to user interactions in a timely manner due to time-consuming operations, improving the smoothness of map rendering and user experience.
[0167] Optionally, in some embodiments, before constructing vertices based on the builder object, the child thread needs to obtain the resource data required by the builder object. Since the child thread cannot directly access resources managed by the main thread, it can send resource requests to the main thread in parallel via reverse communication to obtain icon image data, glyph data, Scalable Vector Graphics (SVG) resources, etc., required for generating texture data. The following section will illustrate this further. Figure 3 The process will be explained.
[0168] Figure 3 A flowchart illustrating the tile rendering method provided in this application embodiment. Figure 2 ,like Figure 3 As shown, S24 includes:
[0169] S31. The child thread sends resource requests to the main thread in parallel via reverse communication.
[0170] Reverse communication refers to a communication method where a child thread actively initiates a request to the main thread. During tile rendering, the main thread is usually responsible for distributing tile loading tasks to child threads. However, when a child thread needs additional resource data during the vertex construction phase, it can request these resources from the main thread through reverse communication.
[0171] The resource requests include at least one of the following: image resource requests, glyph resource requests, and SVG resource requests. Image resource requests are used to obtain icon image data, such as point-of-interest icons and symbol icons. Glyph resource requests are used to obtain glyph data required for text rendering, such as glyph information corresponding to road names and location labels. SVG resource requests are used to obtain vector graphics data, such as vector patterns used for filling or outlining.
[0172] In practical applications, child threads can generate corresponding resource requests based on the resource types required by the builder object. For example, if the builder object needs to display icons, the child thread generates image resource requests; if the builder object needs to display text, the child thread generates glyph resource requests; if the builder object needs vector-filled patterns, the child thread generates SVG resource requests. The child thread sends these resource requests to the main thread simultaneously, so that the main thread can process these resource requests in parallel.
[0173] S32. The main thread responds to the resource request sent by the child thread, calls the corresponding resource manager in parallel to load the resource, and sends the loaded resource data back to the child thread.
[0174] The resource manager is a module in the main thread used to load and manage specific types of resource data, including icon image data manager, font data manager, SVG resource manager, etc. Each resource manager is responsible for handling resource requests of its corresponding type and performing the actual resource loading operation.
[0175] For example, the icon image data manager is responsible for loading the corresponding icon image based on the identifier in the image resource request; the glyph data manager is responsible for generating glyph data based on the character set in the glyph resource request; and the SVG resource manager is responsible for loading and parsing the SVG file based on the identifier in the SVG resource request.
[0176] In practical applications, the main thread can assign an independent loading task to each resource request. These loading tasks can be executed concurrently, thereby reducing the overall loading time. For example, the main thread can simultaneously launch the icon image data manager, font data manager, and SVG resource manager to handle their respective requests, without having to wait for one to complete before launching another.
[0177] Optionally, the resource data includes at least one of the following: icon image data returned by the icon image data manager, glyph data returned by the glyph data manager, and SVG graphic data returned by the SVG resource manager.
[0178] In practical applications, the main thread can encapsulate resource data into messages and send them to child threads.
[0179] S33. After obtaining all the resource data corresponding to the resource request, the child thread constructs vertices based on the builder object, generating vertex buffer data and texture data.
[0180] It's understandable that "all resource data" means that all resource data corresponding to each resource request sent by the child thread has been received. In other words, after sending multiple resource requests in parallel, the child thread needs to wait for the resource data corresponding to all resource requests to be returned before it can begin subsequent vertex construction.
[0181] Optionally, the sub-thread first generates texture data based on the resource data required by the builder object. Then, for the feature data corresponding to each builder object, vertex attribute data is generated based on the texture data and written to the vertex buffer. Finally, the builder objects written to the vertex buffer are grouped by layer name to obtain multiple builder object groups.
[0182] Understandably, the relevant explanations can be found by referring to... Figure 2 The contents of that article will not be repeated here.
[0183] The above embodiments shorten the resource loading wait time from the sum of the loading times of each resource to the maximum value of the loading time of each resource by sending resource requests and loading resources in parallel. This avoids the problem of excessive overall time consumption caused by the serial execution of resource loading and vertex construction, improves the efficiency of resource acquisition in sub-threads, and enables vertex construction to start earlier, thereby shortening the rendering cycle of a single tile. Especially in high-concurrency tile loading scenarios, it can effectively improve rendering throughput and response speed.
[0184] Figure 4 A flowchart illustrating the tile rendering method provided in this application embodiment. Figure 3 ,like Figure 4 As shown, after S23, the method further includes the following steps:
[0185] S41. The child thread quantizes the coordinates of point features in the builder object to a preset precision and generates position keys.
[0186] Coordinate quantization refers to rounding the original coordinates of point elements according to a preset precision, so that coordinates that are very close to each other are merged into the same discrete position, thereby eliminating the small errors generated in the floating-point calculation process.
[0187] In practical applications, the preset precision can be set according to the precision requirements of map rendering; for example, it can be set to 10. -6 This means six decimal places. In the WGS84 coordinate system, this precision corresponds to a distance of approximately 0.11 meters (at the equator), which is sufficient to distinguish the positions of different point features while avoiding misjudgments caused by floating-point errors.
[0188] The position key is a string generated after coordinate quantization, used to identify a discrete location. In practical applications, the sub-thread concatenates the quantized coordinates according to a preset format to generate the position key.
[0189] For example, quantized longitude and latitude can be connected with a colon to generate a location key. It's understood that if two point features have the same location key, it means they are at the same location within the quantization precision range.
[0190] S42. If there are other point features at the position corresponding to the position key, offset the point feature along the preset axis direction and record the offset amount.
[0191] In practical applications, if there are other point elements at the location corresponding to the location key, it means that the two are in the same position within the quantization accuracy range. If the original position is still rendered, they will overlap with other point elements in screen space, making it impossible to distinguish between icons and text labels. Therefore, it is necessary to offset the point elements along the preset axis direction.
[0192] The preset axis direction refers to a pre-defined direction used to offset point features, such as a vertical or horizontal direction. It is understood that the preset axis direction can be set according to the actual rendering effect, and this embodiment does not impose specific limitations on it.
[0193] The offset refers to the distance the current point feature moves relative to its original position along a preset axis. In practical applications, the sub-thread can maintain a cumulative size value for each position key. This cumulative size value represents the total size of the point features already arranged at the position corresponding to that position key. For the current point feature to be processed, if there are no other point features at the position corresponding to that position key, the offset of the current point feature is zero, and the size of the current point feature is recorded as the cumulative size value corresponding to that position key. If there are other point features at the position corresponding to that position key, the offset of the current point feature is equal to the cumulative size value corresponding to that position key. After the offset is completed, the size of the current point feature is added to the cumulative size value so that subsequent point features can continue to be arranged sequentially after the previous point feature.
[0194] For example, assuming a point element already exists at a location key with an icon height of 20 pixels, the current point element is offset by 20 pixels along a preset axis, ensuring that adjacent point elements are joined end-to-end along the preset axis without overlapping. If a third point element appears at this location, its offset is equal to the sum of the sizes of the first two point elements.
[0195] In practical applications, the sub-thread can create an offset record table, using the feature index or location key of the point feature as the key, and store the corresponding offset in the table.
[0196] In practical applications, the sub-thread can iterate through all point features. For the current point feature, it first checks whether other point features already exist at that location based on its position key. If no other point features exist, it records the current point feature's size as the base size for that location, with an offset of zero. If other point features exist, it offsets the current point feature along a preset axis and records the offset. Simultaneously, the sub-thread can update the cumulative size value corresponding to that location so that subsequent point features can continue to offset sequentially.
[0197] S43. Based on the offset, offset the corresponding point features in other builder objects associated with the point features along the preset axis direction.
[0198] The corresponding point features in other builder objects associated with a point feature refer to the corresponding representations of the same geographic point feature in different builder objects. For example, if a point of interest needs to display both an icon and text label, during the symbolization process, the point of interest might be placed into an icon builder object and a text builder object respectively. The point features in the icon builder object are used to generate icon vertex data, while the point features in the text builder object are used to generate text label vertex data. Although they reside in different builder objects, they describe the same geographic point.
[0199] In practical applications, the sub-thread can iterate through the point elements in the text builder object after completing the offset processing of all point elements. For each text-type point element, the sub-thread queries the offset record table to obtain the offset of the icon-type point elements associated with that text-type point element. If a corresponding offset is found, the text-type point element is offset along a preset axis based on that offset. In this way, even if the icon and text overlap with other point elements in their original positions, after synchronous offsetting, the icon and text move as a whole, avoiding overlap while maintaining their association.
[0200] In the above embodiments, by quantizing coordinates and synchronizing offsets, the problem of overlapping icons and text of the same or similar point features can be automatically handled. Each point feature can be visually identifiable without manual configuration, while maintaining the association between icons and text, avoiding image-text separation, improving the readability and aesthetics of map annotations, and ensuring the accuracy and consistency of overlay processing.
[0201] Figure 5 A flowchart illustrating the tile rendering method provided in this application embodiment. Figure 4 ,like Figure 5 As shown, after S22, the method further includes the following steps:
[0202] S51. For point features with the tile restriction option enabled, the sub-thread determines whether the coordinates of the point feature are within the latitude and longitude range of the target tile.
[0203] The tile constraint option is used to mark point features that require tile boundary filtering. In practical applications, some point features may be included in the data of multiple adjacent tiles simultaneously due to tile division rules. If these point features are not processed, the same point feature may be rendered in multiple tiles, resulting in duplicate icons at the junctions of adjacent tiles. The purpose of the tile constraint option is to add a marker to these point features, enabling the sub-thread to identify the point features that require boundary filtering during processing.
[0204] Tile boundary filtering refers to a sub-thread determining whether a point feature should be retained in the vector feature data corresponding to the current target tile based on the relationship between the coordinates of the point feature and the latitude and longitude range of the current target tile. By using tile boundary filtering, it is ensured that each point feature is rendered only within the tile to which its coordinates actually belong, avoiding duplicate rendering across tiles.
[0205] In practical applications, the sub-thread can iterate through each point feature in the vector feature data and check whether the tile restriction option is enabled for that point feature. For point features with the tile restriction option enabled, the sub-thread obtains the coordinates of the point feature and determines whether the coordinates are within the latitude and longitude range of the target tile.
[0206] S52. If not, remove the point feature from the vector feature data.
[0207] If the determination result indicates that the coordinates of a point feature are not within the latitude and longitude range of the target tile, it means that although the point feature is included in the vector feature data corresponding to the current target tile, its actual coordinate position does not belong to that tile. In this case, if the point feature is retained, it will also be drawn when the current target tile is rendered, and the other tile to which the actual coordinates of the point feature belong will also draw the point feature, resulting in duplicate display. Therefore, the sub-thread removes the point feature from the vector feature data, ensuring that the current target tile does not render the point feature, so that the point feature is only rendered in the tile to which its coordinates belong.
[0208] S53. If it exists, then retain that point feature in the vector feature data.
[0209] If the determination result indicates that the coordinates of the point feature are within the latitude and longitude range of the target tile, it means that the coordinates of the point feature actually belong to the current target tile. At this time, the sub-thread retains the point feature in the vector feature data, so that it can be processed and rendered normally in the subsequent symbolization processing and vertex construction of the current target tile.
[0210] In the above embodiments, by using tile boundary filtering, it is ensured that each point feature is rendered only in the tile to which its coordinates belong, which solves the problem of repeated drawing across tiles caused by tile division, avoids the phenomenon of "double shadow" of icons at the splicing of adjacent tiles, improves the accuracy and visual quality of map rendering, and reduces unnecessary vertex construction and rendering overhead, further improving rendering performance.
[0211] To more clearly explain the solutions shown in the above embodiments, several specific embodiments are described below.
[0212] In practical applications, the tile rendering method provided in this application embodiment may include the following steps:
[0213] Step 1: The main thread sends a tile loading task to the child thread.
[0214] Step 2: The sub-thread responds to the tile loading task and obtains the vector feature data corresponding to the tile loading task.
[0215] Step 3: The sub-thread performs symbolization and overlay processing on the vector feature data, generates a builder object to describe the rendering style, and quantizes the coordinates of point features in the builder object.
[0216] Step 4: The child thread sends resource requests to the main thread in parallel via reverse communication. The main thread responds to the resource requests by calling the corresponding resource manager in parallel to load the resources and then sends the loaded resource data back to the child thread.
[0217] Step 5: The sub-thread generates texture data based on the resource data required by the builder object, generates vertex attribute data based on the texture data and writes it to the vertex buffer, and groups the builder objects after writing to the vertex buffer by layer name.
[0218] Step 6: The child thread sends the vertex buffer data and texture data to the main thread.
[0219] Step 7: The main thread creates a rendering object based on the received vertex buffer data and texture data, and adds the rendering object to the rendering scene.
[0220] Next, we will explain the specific implementation details of each step.
[0221] Step 1: The main thread sends a tile loading task to the child thread.
[0222] The tile provider in the main thread calculates a list of tiles to be loaded based on the current viewport. This list includes the identifiers of all target tiles. Loading parameters are constructed for each target tile, and the tile loading task is distributed to child threads via a thread pool. The tile provider is the functional module in the main thread used to determine the identifiers of target tiles based on the current viewport and generate tile loading tasks. The thread pool is a component in the main thread used to manage and schedule multiple child threads. It maintains multiple child threads and distributes tile loading tasks to the appropriate child threads for execution according to a scheduling strategy.
[0223] Step 1.1 Thread pool initialization
[0224] The thread pool creates N child threads during construction, where N defaults to navigator.hardwareConcurrency, which is the number of logical cores of the Central Processing Unit (CPU). Each child thread is created using a Binary Large Object (Blob) Uniform Resource Locator (URL) to resolve cross-domain resource loading issues.
[0225] Specifically, a specified number of child threads can be created using the `initWorkers` function. Within a loop, a new Blob object is created each time. This Blob object contains JavaScript code that loads an EarthWorker script using the `importScripts` function, where EarthWorker is the address of the script the child thread needs to load. Since directly loading external scripts may be subject to cross-origin restrictions, the script address is first written to the Blob object. Then, the `window.URL.createObjectURL` method generates a same-origin Blob URL for this Blob object, and finally, the child thread is created using this Blob URL. This way, the child thread can load the required script immediately after creation. The created child threads are placed in the `workers` array of the thread pool and managed uniformly by the thread pool.
[0226] In practical applications, each child thread is encapsulated as a thread object, and the thread object maintains the following state:
[0227] taskCount: The number of tasks currently being executed. It is used to determine whether the child thread is busy, i.e., whether the number of tasks is greater than or equal to the preset task limit.
[0228] response: A callback function mapping table, using the communication identifier (ID) as the key, to record the callback function corresponding to each task, so that the child thread can find the corresponding callback function and execute it by means of the communication ID after completing the task.
[0229] Step 1.2 Dual-priority queue scheduling
[0230] When the tile provider initiates a tile loading task, it calls a scheduling function. This function receives the tile loading task parameters, a callback function, and the identifier of the target child thread. The specific execution logic of the scheduling function is as follows:
[0231] If the tile loading task carries the identifier of the target sub-thread, and the number of tasks in the target sub-thread has not reached the preset task limit, then the tile loading task will be immediately distributed to the target sub-thread for execution.
[0232] If a tile loading task carries the identifier of a target sub-thread, but the number of tasks for that target sub-thread has reached or exceeded the preset task limit, then the tile loading task will be added to the first queue (_queueUni) to wait.
[0233] If the tile loading task does not carry the identifier of the target child thread, then the tile loading task is added to the second queue (_queue) to wait.
[0234] The first queue stores tile loading tasks that carry the identifier of the target child thread but are currently busy. When the number of tasks for the target child thread is less than the preset task limit, the scheduling function retrieves a tile loading task from the first queue and immediately assigns it to the corresponding target child thread for execution. The second queue stores tile loading tasks that do not carry the identifier of the target child thread. The scheduling function retrieves a task from the head of the second queue and assigns it to any idle child thread for execution.
[0235] In the actual scheduling process, the scheduling function uses the `_update` method to continuously update the schedule. The `_update` method prioritizes the first queue: it iterates through the tile loading tasks in the first queue, and if the corresponding target child thread is idle, the task is immediately dispatched. After the first queue is processed, the second queue is processed: a tile loading task is retrieved from the head of the second queue, and any idle child thread is found and dispatched. Thus, the scheduling priority of the first queue is higher than that of the second queue.
[0236] Each child thread maintains a task counter to determine the taskCount. The maximum number of tasks a single child thread can execute in parallel is a preset upper limit for the number of tasks, for example, 2. When a task is completed, the scheduling function triggers the next round of scheduling through microtasks, ensuring that the queue is checked only after the callback function has finished executing.
[0237] The dual-priority queue scheduling mechanism described above ensures that tile loading tasks carrying the identifier of the target sub-thread are scheduled first, thus allowing tile loading tasks corresponding to the same data source to be processed by the same sub-thread, achieving thread affinity. For example, for a vector data source VectorProvider, all its tile loading tasks use the same identifier of the target sub-thread. When a sub-thread processes a task from this data source for the first time, it caches the feature data, spatial extent, and layer configuration information of that data source. Subsequent tile loading tasks from the same data source are distributed to the same sub-thread, eliminating the need for the sub-thread to retransmit the data source configuration; the spatial query `selectFeatures` can directly use the cached polygon index, thereby improving processing efficiency.
[0238] Figure 6 A flowchart illustrating the tile rendering method provided in this application embodiment. Figure 5 ,like Figure 6 As shown, step 1 includes:
[0239] S601, Call the scheduling function exec.
[0240] Pass in the tile loading task parameters, callback function, and the target child thread's identifier threadId.
[0241] S602. Determine whether the tile loading task carries the target child thread's identifier threadId.
[0242] If yes, then execute S603; otherwise, execute S608.
[0243] S603. Determine if the number of tasks in the target child thread (taskCount) is less than the preset task limit (MAX_EXEC_COUNT).
[0244] If yes, then execute S604; otherwise, execute S609.
[0245] S604. Immediately dispatch the tile loading task to the target child thread for execution.
[0246] S605. Wait for the tile loading task to complete in the target sub-thread, triggering the completion callback.
[0247] S606. Execute the callback function callback(data) and trigger the next round of scheduling update through the microtask Promise.resolve().then() to ensure that the queue is checked only after the callback function has been executed.
[0248] S607, Execute the scheduled update _update().
[0249] S608. Add the tile loading task to the second queue _queue, and then execute S607.
[0250] S609. Add the tile loading task to the first queue _queueUni, and then execute S607.
[0251] S610. Prioritize processing the first queue: Traverse the tile loading tasks in the first queue. If the number of tasks for the corresponding target sub-thread is less than the preset task limit, then distribute the task to the target sub-thread for execution; if it is greater than or equal to, then keep the task in the first queue and continue traversing the next task in the first queue until all tasks in the first queue have been processed.
[0252] S611, Process the second queue: Take the tile from the head of the second queue to load the task, and find an idle child thread.
[0253] S612. Determine if an idle child thread has been found; if yes, execute S613; otherwise, execute S614.
[0254] S613. Distribute the tile loading task in the second queue to the idle sub-thread and end this scheduling.
[0255] S614. Place the tile loading task back to the head of the second queue _queue and stop this scheduling.
[0256] It should be understood that the relevant explanations in this embodiment can refer to the relevant content in the above embodiments, and will not be repeated here.
[0257] Existing WebWorker thread pools typically employ a global unified queue, scheduling all tasks to any idle sub-thread in a first-in, first-out (FIFO) order. However, in vector tile scenarios, different tile loading tasks from the same data source should ideally be processed on the same sub-thread, as this sub-thread has already cached the feature data, spatial extent, and layer configuration of that data source. Global queues cannot guarantee this thread affinity, leading to redundant data transmission and parsing overhead. For example, in existing solutions, sub-thread scheduling uses a simple round-robin strategy, sequentially assigning tile loading tasks to different sub-threads. When multiple tile loading tasks from the same data source are assigned to different sub-threads, each sub-thread needs to independently load and parse the style configuration and vector feature data of that data source, resulting in wasted memory and redundant computation. Therefore, existing technologies suffer from the problem of redundant data transmission and parsing due to a lack of thread affinity in scheduling. In this embodiment, the main thread uses a dual-priority queue for scheduling, ensuring that tile loading tasks corresponding to the same data source all carry the same target sub-thread identifier. This prioritizes tasks from the same data source to be processed on the same sub-thread, achieving thread affinity, avoiding redundant data transmission and parsing, and solving the aforementioned problems.
[0258] Step 2: The sub-thread responds to the tile loading task and obtains the vector feature data corresponding to the tile loading task.
[0259] The entry module in the sub-thread instantiates the corresponding data source worker based on the data source type. The data source worker is the execution module in the sub-thread responsible for loading and preprocessing data from a specific type of data source. Different data source workers correspond to different types of data sources, such as vector data source workers, vector tile data source workers, etc.
[0260] Step 2.1 Child thread entry point dispatch
[0261] The child thread entry point receives messages sent by the main thread and distributes tasks to the corresponding data source workers based on the data source identifier (data.source) in the message.
[0262] Specifically, `sourceCls` is a mapping table between data source types and data source worker classes. It records the data source worker classes corresponding to vector data sources (vector), vector tile data sources (vectorTile), image data sources (image), WFS tile data sources (wfsTile), and full render data sources (fullRender). The `getSource` function internally searches for a cached data source worker instance based on the data source identifier. If it doesn't exist, it retrieves the corresponding worker class from the `sourceCls` mapping table based on the data source type, creates a new instance, and caches it. The `onmessage` function is the message handling function of the child thread entry module. When the child thread receives a message from the main thread, this function deconstructs the data portion (`data`), communication ID, and task type (`type`) from the message body `e.data`. Then, it deserializes the `data` using the `deserialize` function to restore the data content sent by the main thread. If the data contains a data source identifier (`source`), the `getSource` function is called to find or create the corresponding data source worker instance based on the data source identifier. Then, using the task type (`type`) as the method name, the corresponding method on that data source worker instance is called, passing in the communication ID and the data `data`. In this way, the tile loading tasks sent by the main thread can be distributed to the corresponding data source workers for processing.
[0263] It's important to note that the `getSource` function finds or creates a corresponding data source worker instance based on the data source identifier, ensuring that all requests for the same data source are handled by the same data source worker instance. This allows the data source worker instance to cache the state of the data source, eliminating the need for repeated initialization in subsequent requests and thus improving processing efficiency.
[0264] Step 2.2 Spatial query of vector data source
[0265] For vector data sources, the vector data source worker uses polygons in the loadTile method to perform geometric intersection judgment and filter vector feature data within the target tile range.
[0266] Specifically, the `loadTile` method calculates the rectangular area `rect` corresponding to the tile based on the target tile identifier in the tile loading task parameter `param` using the `tilingScheme.tileXYToRectangle` method. `tileBuffer` is the buffer size carried in the task parameter `param`, in degrees; here, it is converted to radians by multiplying by π / 180 for use when generating the coordinate array `coordinates`. Then, the coordinate array `coordinates` is generated based on the tile area plus the buffer, and a polygon object `polygon` is constructed. Next, the `selectFeatures` method is called, passing in the polygon object `polygon` and the layer list `layers`, to filter vector feature data that intersects with the target tile area from the vector data source. Finally, the filtered vector feature data `data` and the task parameter `param` are passed to the `parse` method for further processing.
[0267] The `selectFeatures` method iterates through the feature list of each layer, determining whether the geometry of each feature intersects with the area represented by the polygon object, and retains only the intersecting features. In this way, the vector data source worker can accurately retrieve the vector feature data corresponding to the target tile from the cached data source, avoiding subsequent processing of irrelevant features.
[0268] Step 2.3 Decoding the Vector Tile Data Source
[0269] For vector tile data sources, the vector tile data source worker receives the tile data packet (ArrayBuffer) downloaded by the main thread and decodes it in a child thread to obtain vector feature data.
[0270] Specifically, the `loadTile` method first creates a text decoder `enc`, specifying the decoding format as UTF-8. Then, it converts the tile data packet `raw` to an unsigned 8-bit integer array `uint8` for byte-by-byte processing. Here, `raw` represents the binary data corresponding to the tile data packet received by the child thread. Next, the byte array is decoded into a string using the `enc.decode` method, and then parsed into a JSON object `response` using the `JSON.parse` method. The `response` contains the data format identifier `dataType` and the data content. If the data format identifier is `pbf`, the `pbfUtil.base64ToJson` method is called to decode `response.data`, passing in the `ratio` and `dimension` parameters to obtain the vector feature data `data`. If the data format identifier is `json-pbf`, it indicates a mixed encoding format, requiring decoding by layer. After decoding, `data` and the task parameter `param` are passed to the `parse` method for further processing. In this way, the vector tile data source worker can decode the binary format tile data packet into usable vector feature data.
[0271] Step 2.4 Data Filtering
[0272] After obtaining the vector feature data, the sub-thread performs two levels of filtering on the vector feature data: rendering range filtering and tile boundary filtering.
[0273] First-level rendering range filtering: If the main thread sets a global rendering range constraint (renderFilterBox, a 3D cube range), then spatial containment is checked for each feature in the vector feature data. If a feature is not within the global rendering range constraint, it is removed from the vector feature data. This ensures that only features within the user's current area of interest are retained, reducing the amount of data processed subsequently.
[0274] Second-level tile boundary filtering: For point features with the tileRestrict option enabled, determine whether the coordinates of the point feature are within the latitude and longitude range of the target tile. If not, remove the point feature from the vector feature data. The tileRestrict option is used to mark point features that require tile boundary filtering, ensuring that each point feature is rendered only within the target tile to which its coordinates belong, thus resolving the issue of repeated rendering across tiles.
[0275] Through the above two-level filtering, the sub-thread can remove unnecessary feature data, ensuring that subsequent symbolization processing and vertex construction are only performed on valid features, thereby improving rendering performance.
[0276] Existing solutions typically render the feature in every tile, causing the same feature to be displayed repeatedly at tile boundaries, resulting in a visual "double image." Some existing solutions address this by hiding overlapping items, but this does not fundamentally solve the problem of cross-tile rendering and also leads to the loss of some feature display. Therefore, existing technologies suffer from the problem of cross-tile rendering. In this embodiment, after the sub-thread obtains the vector feature data, it performs tile boundary filtering on point features with the tile restriction option enabled, determining whether the coordinates of the point feature are within the latitude and longitude range of the target tile. If not, the point feature is removed from the vector feature data, thereby ensuring that each point feature is rendered only in the tile to which its coordinates belong, thus solving the problem of cross-tile rendering.
[0277] Step 3: The sub-thread performs symbolization and overlay processing on the vector feature data, generates a builder object to describe the rendering style, and quantizes the coordinates of point features in the builder object.
[0278] Symbolization processing refers to converting vector feature data into multiple builder objects by calling the corresponding renderer's symbol construction method based on the renderer configuration of the layer. Each builder object contains the builder object type, a feature data list, and rendering style parameters. The builder object type can be a point builder, line builder, polygon builder, or text builder, etc.; the feature data list records the set of features that the builder object needs to process; and the rendering style parameters include specific rendering information such as material, offset, and rotation.
[0279] The renderer acts as a bridge between vector feature data and builder objects, determining the symbol type and style to be used for each feature based on its attributes and the current zoom level.
[0280] Overlapping refers to the phenomenon where multiple point features on a map, located at the same or similar geographic coordinates, cause their icons and labels to overlap in screen space, making them visually indistinguishable. This application's embodiments employ a coordinate quantization and offset stacking strategy, and synchronously offset related text features to automatically handle the overlap problem.
[0281] Step 3.1 Coordinate Quantization
[0282] To avoid the same coordinates generating different position keys due to floating-point precision, the coordinates are quantized to a preset precision (10). -6 ).
[0283] Specifically, the quantization coefficient exp can be set to 10. 6For each coordinate value in the coordinate array, the coordinate value can be multiplied by the quantization factor, rounded down, and then divided by the quantization factor to truncate the coordinate to 6 decimal places. The quantized coordinates are then joined together with a colon using the join(':') method to generate a position key ckey. In this way, identical or very close coordinates will be merged into the same position key, avoiding misjudgments caused by floating-point errors.
[0284] In the WGS84 coordinate system, latitude and longitude 10 -6 The degree is approximately equal to 0.11 meters (at the equator), which is sufficient to distinguish the location of different point elements and avoid misjudgment caused by floating-point errors.
[0285] Step 3.2 Offset Stacking
[0286] Point elements at the same position are stacked and offset along a preset axis, and the offset is accumulated based on the existing cumulative size value.
[0287] Specifically, pointsOffset is used to record the cumulative size value corresponding to each position key, and indexOffset is used to record the offset of each point feature. Initially, it can be an empty object or an empty array, which is gradually filled during the offset stacking process. When a position key already exists, it means that there are other point features at that position. At this time, the offset of the current point feature (feat.offset[1], which represents the offset component along the preset axis direction) is increased by pointsOffset[key], which is the cumulative size value of the existing point feature; at the same time, the value of pointsOffset[key] is recorded in indexOffset, with the feature index feat.featureIndex of the point feature as the key, so as to facilitate subsequent synchronous offset. Then, the size feat.size of the current point feature is accumulated to pointsOffset[key] so that the subsequent point features continue to be arranged in sequence. If the position key appears for the first time, the size feat.size of the current point feature is used as the cumulative size value of the position, and the offset of the point feature is recorded as 0.
[0288] Step 3.3 Text Synchronization Offset
[0289] Iterate through the text builder objects and synchronize the offsets generated by the icon builder objects to the associated text elements. This offset synchronization ensures that the text labels and corresponding icons maintain the same offset, preserving the visual relationship between the icons and text.
[0290] Specifically, builders.forEach iterates through all builder objects. For text builder objects of type Text, it further iterates through each feature feature in its feature data list. If the feature is a point feature and there is an offset corresponding to the feature index of the point feature in indexOffset, then the offset is added to the feature feature's feature.offset[1], thereby realizing the synchronous offset of the corresponding point feature in the text builder object along the preset axis direction. In this way, even if the icon and text overlap with other point features in their original positions, after the synchronous offset, the icon and text move as a whole, which avoids overlap and maintains the correlation.
[0291] Figure 7 A flowchart illustrating the tile rendering method provided in this application embodiment. Figure 6 ,like Figure 7 As shown, step 3 includes:
[0292] S701. Input a list of builder objects.
[0293] S702, First pass: Process icon class builder objects.
[0294] S703. Quantize the coordinates of point elements in the icon builder object to generate position key ckey, offset key okey, and rotation key rkey.
[0295] The rotation key is a key value used to identify the rotation angle of point features. In practical applications, some point features may have rotation attributes; for example, icons need to be rotated at a certain angle for display. To distinguish point features with different rotation angles during overlay processing and avoid incorrectly merging point features with different rotation states into the same stacking position, rotation keys can be generated based on the rotation angle of the point features. For example, the rotation angle can be quantized to a preset precision and rounded down to serve as the rotation key. In this way, even if two point features have the same coordinates, as long as their rotation angles are different, the unique keys they generate will be different, thus preventing them from being considered as being in the same position and offset during stacking.
[0296] S704. Generate a unique key key based on the position key ckey, the offset key okey, and the rotation key rkey, i.e., key = ckey - okey - rkey.
[0297] S705. Determine if the unique key already exists in the offset dictionary.
[0298] If yes, then execute S706; otherwise, execute S708.
[0299] S706. Increase the offset of the current point feature by the value of the offset dictionary [key], and record the value of the offset dictionary [key] as the offset of the point feature, using the feature index of the point feature as the key.
[0300] S707. Accumulate the size of the current point feature into the offset dictionary [key], and update the cumulative size value corresponding to this position.
[0301] S708. Set the offset dictionary [key] to the size of the current point feature and record the offset of the point feature as 0; then proceed to S709.
[0302] S709. Determine if there is another point feature to process; if yes, return to S703 to process the next point feature; if no, execute S710.
[0303] S710, Second pass: Processing text class builder objects.
[0304] S711. Determine if the offset of the feature index (index) of the point feature in the text class builder object exists and is non-zero; if yes, execute S712; if no, execute S713.
[0305] S712, Increase the offset of the point feature by the offset corresponding to the index of the feature, so that the point features in the text builder object and the associated point features in the icon builder object are offset synchronously; then proceed to S714.
[0306] S713, No offset processing is performed; then proceed to S714.
[0307] S714. Determine if there is another text element to be processed; if yes, return to S711 to process the next text element; if no, execute S715.
[0308] S715, Output the list of builder objects after offset processing.
[0309] In map rendering, multiple point features (such as point-of-interest icons) may be located at the same or similar geographic coordinates, leading to problems such as overlapping icons and text, making them visually indistinguishable, or some features being hidden and not fully displayed in existing technologies. Traditional GIS software typically performs overlay processing on the server side, but in the WebGIS client rendering architecture, the server cannot perceive the client's screen space layout, thus requiring overlay processing on the client side. It is evident that existing technologies suffer from incomplete graphic feature overlay processing or lack of support for automatic offsetting. In this embodiment, a sub-thread quantizes the coordinates of point features in the builder object, generates position keys, offsets and stacks point features at the same position along a preset axis, and synchronizes the offset to the corresponding point features in the associated text-type builder object, thereby achieving automatic staggered display of point features and solving the problem of incomplete graphic feature overlay.
[0310] Step 4: The child thread sends resource requests to the main thread in parallel via reverse communication. The main thread responds to the resource requests by calling the corresponding resource manager in parallel to load the resources and then sends the loaded resource data back to the child thread.
[0311] Before constructing vertices based on the builder object, the child thread needs to obtain the resource data required by the builder object.
[0312] Resource data refers to tile data packages such as images, glyphs, and vector graphics used to generate texture data, and may include at least one of icon image data, glyph data, and SVG graphic data.
[0313] To efficiently acquire this resource data, the child thread can first use the builder factory to instantiate the corresponding builder subclass based on the type information recorded in each builder object, thus initializing the builder object. The builder factory is a module in the child thread used to create builder objects based on the builder type name. It can find the corresponding builder subclass based on the builder type name recorded in the builder object and call the constructor of that builder subclass to complete the creation of the builder object.
[0314] After the child thread creates the builder objects, it needs to determine the resource types required by each builder object and send resource requests to the main thread in parallel via reverse communication. Resource requests include at least one of the following: image resource requests, glyph resource requests, and SVG resource requests.
[0315] The main thread responds to resource requests sent by child threads by concurrently calling the corresponding resource manager to load resources and then sending the loaded resource data back to the child threads. Once the child threads have received the resource data for all resource requests, a callback is triggered, and the subsequent vertex construction process continues. In this way, the resource loading wait time is reduced from the sum of the loading times of each resource to the maximum value of the loading time of each resource, thereby improving resource acquisition efficiency.
[0316] Step 4.1 The child thread initiates a resource request.
[0317] The child thread initiates resource requests to the main thread through a reverse communication mechanism to achieve parallel loading of multiple resources. The specific working process of the reverse communication mechanism is as follows: The child thread calls the POST_REQUEST function to register the request type, request parameters, and callback function in the child thread's callback mapping table; subsequently, the child thread sends the resource request to the main thread via postMessage; after receiving the resource request, the main thread calls the corresponding resource manager to load the resource; after the main thread finishes loading, it sends the resource data back to the child thread via postMessage; after receiving the response, the child thread looks up the corresponding callback function based on the communication ID and executes it.
[0318] Specifically, the `prepareResource` function is used to simultaneously request icon image data, glyph data, and SVG graphic data. This function receives an array of image URLs (`imageURLs`), an array of glyph keys (`glyphKeys`), an array of SVG URLs (`svgURLs`), and a callback function (`callback(data)`) as parameters. For simplicity, the code uses `callback(data)` to represent the callback function. When the resource data corresponding to the request is returned, the resource data is written to the `resource` object, and the corresponding ready flag is set to `true`. Internally, the function first initializes the `resource` object, which stores the requested icon image data and SVG graphic data. It also defines three ready flags: `imageReady`, `glyphReady`, and `svgReady`, all initially set to `false`. For each type of resource, if the corresponding array length is greater than 0, the `POST_REQUEST` function is called to send a resource request of the corresponding type to the main thread, passing in the callback function. During execution, this callback function writes the returned resource data to the `resource` object and sets the corresponding ready flag to `true`. If the array is empty, the corresponding ready flag is simply set to `true`. When all three ready flags are true, it means that all required resource data is ready. At this point, the callback function is invoked, passing in the collected resource data. This allows for parallel sending of multiple resource requests and unified processing once resources are ready. Here, `self` refers to the global object of the child thread, and `POST_REQUEST` is the function within the child thread used to send resource requests to the main thread.
[0319] Step 4.2 The main thread processes resource requests.
[0320] After receiving a resource request from a child thread, the Earth scene object in the main thread calls the corresponding resource manager to load the resource. The Earth scene object is the core object in the main thread used to manage the rendering scene and resource loading. The resource managers include an image manager, a glyph data manager, and an SVG resource manager, which are used to handle image resource requests, glyph resource requests, and SVG resource requests, respectively.
[0321] The image manager loads image URLs and generates ImageBitmap objects. ImageBitmap objects are bitmap objects provided by the browser, which can be directly sampled by the graphics processor. The main thread then sends the generated ImageBitmap object back to the child thread as icon image data.
[0322] The glyph data manager is used to draw characters on the Canvas using the TinySDF algorithm, extract the alpha channel, and perform Euclidean distance transformation (EDT) to generate signed distance field (SDF) glyph data. TinySDF is an algorithm for generating signed distance field glyph data, EDT is Euclidean distance transformation, and SDF is signed distance field. SDF glyph data remains sharp during scaling and is suitable for rendering map text labels. The main thread sends the generated SDF glyph data back to the child thread as glyph data.
[0323] The SVG resource manager is used to load SVG files, parse the SVG files using DOMParser, extract the symbol elements, and convert the symbol elements into independent SVG graphic data. The main thread then sends the converted SVG graphic data back to the child thread.
[0324] Through the processing of the resource manager described above, the main thread can obtain the icon image data, glyph data and SVG graphic data required by the child thread in parallel, and send them back to the child thread in a timely manner, so that the child thread can continue to build vertexes after all resources are ready.
[0325] In existing technologies, vector tile rendering relies on various external resources, such as icon image data, glyph data, and dashed line textures. It typically employs a sequential process of loading all resources first, followed by vertex construction. However, resource loading involves network requests and image decoding, the time consumption of which is unpredictable; vertex construction involves substantial computation, and its time consumption is directly proportional to the number of features. When both are executed sequentially, the total time is the sum of the time spent loading each resource and the time spent constructing the vertex.
[0326] For example, in existing solutions, the main thread needs to sequentially identify the required icon, request the image, wait for image decoding, request the glyph, and wait for glyph generation before vertex construction can begin. Image and glyph requests are issued serially, and vertex construction can only begin after all resources are ready. It is evident that existing technologies suffer from the problem of long overall execution time due to the serial execution of resource loading and vertex construction.
[0327] In this embodiment, the child thread sends image resource requests, glyph resource requests, and SVG resource requests to the main thread in parallel via reverse communication. The main thread calls the corresponding resource manager in parallel to load the resources and send them back. The child thread performs vertex construction after all resource data is ready, thereby reducing the resource loading waiting time from the sum of the loading times of each resource to the maximum value of the loading time of each resource, thus solving the problem of the above-mentioned serial execution.
[0328] Step 5: The sub-thread generates texture data based on the resource data required by the builder object, generates vertex attribute data based on the texture data and writes it to the vertex buffer, and groups the builder objects after writing to the vertex buffer by layer name.
[0329] Once the resource data is ready, the sub-thread executes texture atlas packaging and vertex construction. Texture atlas packaging employs a dual-atlas strategy, combining independent and shared atlases. The texture atlas packages the data that needs to be sampled by the graphics processor in texture form, such as icon image data and optional glyph data in image form. SVG graphic data is passed directly to the builder object as independent resource data and does not participate in texture atlas packaging. The icon image data of some builder objects may change dynamically at runtime, for example, if the icon needs to be changed. In this case, a dedicated texture atlas needs to be managed for these builder objects for individual updates; while the resource data of other builder objects is relatively stable and suitable for sharing the same texture atlas to reduce the number of texture bindings by the graphics processor.
[0330] Step 5.1 Packaging of Independent Image Sets
[0331] For builder objects that require independent atlases, call their createImageAtlasIfNeed method to create a dedicated texture atlas, which contains only the icon image data required by the builder object.
[0332] Specifically, `allBuilders` is a collection of all builder objects in the current tile. `builderImages` records the correspondence between each builder object's identifier and its required icon image data. When iterating through `allBuilders`, for each builder object, `builder.id` is used to retrieve its required icon image data `images`. Then, the `createImageAtlasIfNeed` method of that builder object is called, passing in `resource.images` and `images`. `resource.images` is the collection of icon image data obtained in step 4. If this method returns an `imageAtlas` object, it means that the builder object needs an independent atlas and it has been successfully created. At this point, the `imageAtlas` is stored in the `imageAtlases` collection with `imageAtlas.id` as the key. Then, `builder._postResourceLoaded(imageAtlas)` is called to notify the builder object that the resource has been loaded, and the `builder.build` method is called, passing in the independent atlas and SVG graphics data for subsequent vertex construction. If `createImageAtlasIfNeed` returns an empty value, it means that the builder object does not need an independent atlas, so it is added to the `shareImageAtlasBuilders` array for later use of the shared atlas.
[0333] Step 5.2 Packaging the shared image atlas
[0334] For other builder objects that do not require independent atlases, their icon image data is aggregated and then packaged into a shared texture atlas using the GrowingPacker 2D binning algorithm.
[0335] Specifically, `packImageSet` is a set of identifiers for the icon image data required for the shared atlas. It is generated by collecting the icon image data identifiers needed for each builder object while iterating through `shareImageAtlasBuilders`. By iterating through `packImageSet`, the corresponding icon image data is retrieved from `resource.images` and stored in `packImages` objects. Then, using the `ImageAtlas` class and passing in `packImages`, the GrowingPacker 2D binning algorithm is used to compactly pack these icon image data to generate the `sharedImageAtlas` shared texture atlas. Afterwards, `shareImageAtlasBuilders` is iterated through, and `_postResourceLoaded(resource)` is called on each builder object to notify that the resource has been loaded. The `builder.build` method is then called, passing in the shared texture atlas and SVG graphics data for subsequent vertex construction.
[0336] It should be noted that the GrowingPacker 2D binning algorithm is used to arrange multiple images of different sizes into a single texture atlas in a reasonable manner, thereby reducing the waste of texture space. If the glyph data exists in image form, it will also participate in the texture atlas packaging in the same way as described above; if the glyph data has been generated into independently sampleable data by the glyph data manager in step 4, it can be directly passed to the builder object without participating in the texture atlas packaging. This application embodiment does not impose specific restrictions on this.
[0337] Step 5.3 Vertex Construction
[0338] Each builder object calls the `build(dependencies)` method, iterates through its feature data list, and calls the `buildOne(feature, dependencies)` method for each feature data to generate vertex attribute data, including position, color, UV coordinates, normals, etc., and writes the vertex attribute data into a vertex buffer of type `StructArrayFloat32`. After construction is complete, builder objects with empty vertex buffers, i.e., builder objects that have not generated any vertex data, are filtered out, and the valid builder objects are grouped by layer name.
[0339] Specifically, the `build` method receives the `dependencies` parameter, which contains the dependency data required for building the builder object, such as texture atlases and SVG graphics data. The `buildOne` method generates corresponding vertex attribute data for a single feature data point. The UV coordinates in the vertex attribute data indicate which region of the texture atlas the vertex samples color from. A structured floating-point array is an array structure that stores floating-point numbers consecutively in vertex attribute order, making it easy for the graphics processor to read directly. Filtering empty builder objects avoids rendering builder objects without valid data, improving rendering efficiency. After grouping valid builder objects by layer name, multiple builder object groups are obtained. Each builder object group contains one or more builder objects from the same layer and their corresponding vertex buffers.
[0340] In this way, the child thread completes the process of generating texture data based on the resource data required by the builder object, generating vertex attribute data based on the texture data and writing it into the vertex buffer, and grouping the builder objects after writing them into the vertex buffer by layer name.
[0341] Step 6: The child thread sends the vertex buffer data and texture data to the main thread.
[0342] After constructing the vertices, the child thread needs to send the generated vertex buffer data and texture data to the main thread so that the main thread can create a rendering object and complete the rendering based on this data. In practice, the child thread can encapsulate the vertex buffer data and texture data into a message and send it to the main thread using a message passing mechanism. Since the vertex buffer data may contain binary data and the texture data may be image data, directly copying this data would incur significant overhead. Therefore, in one possible implementation, the child thread uses a combination of serialization and zero-copy transfer to efficiently send the vertex buffer data and texture data to the main thread.
[0343] Serialization refers to the process of converting data to be transmitted according to a preset format when data is transferred between the main thread and child threads. In this embodiment, a custom serialization / deserialization mechanism can be used. Specifically, a decorator class can be registered to automatically serialize and deserialize data, and configuration can be used to exclude attributes that do not need to be transmitted, as well as to perform shallow copy instead of recursive serialization to improve serialization efficiency.
[0344] Zero-copy transfer refers to a transfer method where the browser transfers ownership of transferable objects from the sending thread to the receiving thread without performing a memory copy. Transferable objects are objects whose memory ownership can be directly transferred between different threads without copying, such as ArrayBuffer, ImageData, and ImageBitmap. ArrayBuffer represents a binary data buffer, ImageData represents image pixel data, and ImageBitmap represents a bitmap object that can be directly sampled by the graphics processor. During data transfer, the child thread can identify these transferable objects, collect them into a transferable object list, and implement zero-copy transfer through the second parameter of the browser's postMessage interface. After zero-copy transfer is complete, references to these transferable objects in the sending thread become unavailable, thus avoiding data races.
[0345] Specifically, the `post` function is used to send data from a child thread to the main thread. This function receives a communication ID, a task type (`type`), and the data to be sent (`data`) as parameters. Internally, the function first initializes an empty list of transferable objects (`transferables`). Then, it calls the `serialize` function to serialize the `data`, which automatically identifies transferable objects within the `data` and adds them to the `transferables` list. Finally, it calls the `this._worker.postMessage` method to send a message containing the communication ID, the task type (`type`), and the serialized data (`data`), passing `transferables` as the second parameter to achieve zero-copy transmission of transferable objects. Here, `this._worker` represents the communication object corresponding to the child thread, used to send messages to the main thread.
[0346] It's worth noting that the `serialize` function can automatically serialize data based on registered decorator classes, and identify and collect transferable objects during the serialization process. Serialization overhead can be further reduced by configuring the exclusion of unnecessary attributes from transmission and using shallow copies.
[0347] In this way, the child thread completes the process of sending vertex buffer data and texture data to the main thread.
[0348] The main thread's tile provider receives the construction results returned by the child thread. These results may include vertex buffer data, texture data, and optional feature data. Based on this data, the main thread performs operations such as decoding feature data, creating texture objects, creating render objects, initializing render objects, and adding render objects to the rendering scene, thus completing the creation and mounting of the render objects.
[0349] Figure 8 A flowchart illustrating the tile rendering method provided in this application embodiment. Figure 7 ,like Figure 8 As shown, steps 2-6 include:
[0350] S801, Start.
[0351] S802. Call the render range filtering method filterByRenderFilterBox to filter elements that are not within the global render range constraints.
[0352] S803. Call the tile boundary filtering method filterByTile. For point features with the tile restriction option enabled, determine whether their coordinates are within the latitude and longitude range of the target tile, and remove point features that are not within the range.
[0353] S804, Traverse each layer.
[0354] S805. Obtain the vector feature data (feature) corresponding to the current layer, i.e., feature=data[layer.type].
[0355] S806. Get the renderer corresponding to the current layer, i.e., render=Render[layer.render].
[0356] S807. Call the renderer's symbol construction method getSymbolBuilders to convert the vector feature data of the current layer into multiple builder objects, resulting in a list of builder objects named builders, i.e., builders = render.getSymbolBuilders.
[0357] S808. Call the filter method builders.filter(...) to filter out empty builder objects from the list of builder objects.
[0358] S809. Call the overlap handling method resolveOverlap(builders) to quantize the coordinates of point features in the builder object, offset and stack point features at the same position, and simultaneously offset the corresponding point features in the associated text builder object.
[0359] S810. Call the BuilderFactory.create(...) method of the builder factory to instantiate the corresponding builder subclass and complete the initialization of the builder object.
[0360] S811. Call the resource data collection method builder.collectDependencies() to collect the resource data required for each builder object.
[0361] S812. The collected resource data is aggregated into the global resource data set and deduplicated.
[0362] S813. Determine if there is a next layer; if yes, return to S804; otherwise, execute S814.
[0363] S814. Call the parallel resource loading method prepareResource to send image resource requests, glyph resource requests, and SVG resource requests to the main thread in parallel via reverse communication.
[0364] S815: Once the icon image data, font data, and SVG graphic data are all ready, trigger the callback.
[0365] S816, Traverse all builder objects.
[0366] S817. Determine if the current builder object has an independent atlas requirement; if yes, execute S818; if no, execute S819.
[0367] S818: Build a custom texture atlas for the current builder object; then proceed to S820.
[0368] S819. Collect the resource data required by the current builder object into the shared atlas collection; then proceed to S820.
[0369] S820. Determine if there is another builder object; if yes, return to S816; otherwise, execute S821.
[0370] S821. Use the GrowingPacker 2D binning algorithm to pack the resource data in the shared atlas set and create a shared texture atlas.
[0371] S822. Call the build(...) method of the shared atlas builder object to construct vertices.
[0372] S823. Filter builder objects with empty vertex buffers and group the remaining builder objects by layer name.
[0373] S824. Call the response method POST_RESPONSE(...) to send a zero-copy copy of the build result back to the main thread via a transferable object.
[0374] S825, End.
[0375] 7. The main thread creates a rendering object based on the received vertex buffer data and texture data, and adds the rendering object to the rendering scene.
[0376] Step 7.1 Decode feature data
[0377] In one possible implementation, the construction result returned by the child thread also includes binary format feature data (ArrayBuffer). The main thread can decode this feature data into a JSON object for subsequent feature interaction queries. For example, when a user clicks on the map, the attribute information of the clicked feature can be quickly obtained through this JSON object.
[0378] Specifically, `features` refers to binary format feature data returned by the child thread. The main thread decodes `features` into a string using the `THREE.LoaderUtils.decodeText` method, and then parses the string into a JSON object `jsonObj` using the `JSON.parse` method. This JSON object can be stored in the rendered object for subsequent interactive queries.
[0379] Step 7.2 Create a texture object
[0380] The main thread creates texture objects for the texture data returned by the child thread. This texture data can include shared texture atlases and independent texture atlases. The main thread creates corresponding WebGL texture objects for both the shared and independent texture atlases, and sets the texture filtering mode to linear filtering to ensure smooth texture scaling.
[0381] Specifically, `sharedImageAtlas` is a shared texture atlas object, and its `image` property contains the image data corresponding to the texture atlas. If `sharedImageAtlas` exists and its `image` property is valid, a WebGL texture object `sharedTexture` is created using that image data; otherwise, `sharedTexture` is null. Similarly, the main thread also creates corresponding WebGL texture objects for individual texture atlases. A WebGL texture object is an object in the graphics processor used to store texture data; the main thread uses it as part of the material for sampling during rendering.
[0382] Step 7.3 Create a rendering object
[0383] The main thread iterates through the list of builder objects for each layer, calling builder object conversion methods (such as the `_createSymbol` method) to wrap the builder objects into render objects. Render objects can be mesh objects, which consist of geometry and material. The geometry describes vertex data, and the material describes surface appearance properties and references the corresponding WebGL texture objects. The main thread combines the geometry and material into a mesh object, which is the render object.
[0384] Specifically, LayerNames represents the set of layer names involved in the current tile. The main thread iterates through LayerNames, and for each layer name, retrieves the list of builder objects corresponding to that layer from Layers, and calls the _createSymbol method to convert each builder object into a rendering object symbol. The _createSymbol method internally creates geometry and materials, and combines them into a mesh object. Here, textures is the collection of WebGL texture objects corresponding to independent texture atlases, sharedTexture is the WebGL texture object corresponding to shared texture atlases, imageAtlases is the collection of independent texture atlases, and sharedImageAtlas is the shared texture atlas object. After the conversion, the main thread adds the generated rendering object symbols to the grouping object of the corresponding layer.
[0385] Step 7.4 Initialize the rendering object
[0386] The main thread sets the necessary WebGL rendering states for each rendered object, including vertex attributes, index buffers, textures, and uniform variables. The index buffer stores vertex indices, reducing redundant vertex data; uniform variables are global variables that remain unchanged within the graphics processor shader, used to pass material parameters, transformation matrices, and other information. By setting these rendering states, it ensures that the rendered object is displayed correctly during subsequent drawing processes.
[0387] Specifically, `constructor` is the constructor function for the render object. If the `isBuilder` property of the passed-in data is true, then that data is assigned to `this._builder`, indicating that the render object is generated by the constructor object. Subsequently, the `this._createRenderObject()` method is called to create the corresponding mesh object `this._object`. Inside the `_createRenderObject` method, the main thread can complete operations such as geometry and material creation, vertex attribute setting, texture binding, and Uniform variable initialization.
[0388] Step 7.5 Add to the scene
[0389] The main thread adds rendering objects to the corresponding layer's group in the rendering scene. The rendering scene is a tree structure used to organize and manage all rendering objects. Groups are used to hold rendering objects within the same layer to achieve layer-by-layer rendering. By adding rendering objects to the corresponding layer's group, the main thread ensures that the rendering objects are rendered by the graphics processor in layer order, thus guaranteeing the correct occlusion relationships and overlay order between different layers in the map.
[0390] In this way, the main thread completes the process of creating a rendering object based on the received vertex buffer data and texture data, and adding the rendering object to the rendering scene.
[0391] In conclusion, Figure 9 This is a schematic diagram of the data flow of the tile rendering method provided in the embodiments of this application, such as... Figure 9 As shown, the tile provider in the main thread determines the target tiles to be loaded based on the current viewport and distributes the tile loading tasks to the thread pool. The thread pool schedules tasks through a first queue and a second queue, and also through a dual-priority queue. The thread pool assigns the tile loading tasks to the corresponding thread wrapper object of the child thread. The thread wrapper then sends the tile loading tasks to the child thread's Worker entry point via serialization or zero-copy transferable object transmission. The child thread entry point distributes the tile loading tasks to the corresponding data source worker—vector data source worker, vector tile data source worker, or image data source worker—based on the data source type. Each data source worker inherits from the data source worker and sequentially executes data filtering, overlay processing, builder creation, resource data collection, texture atlas packaging, and vertex construction.
[0392] During the resource data collection phase, the sub-thread sends resource requests in parallel to the main thread's image manager, glyph manager, and SVG manager via POST_REQUEST. After each manager completes its loading, it sends the resource data back to the sub-thread for use in texture atlas packaging and vertex construction. Once vertex construction is complete, the sub-thread sends the construction results back to the main thread via POST_RESPONSE using a zero-copy transferable object method. The main thread then creates a rendering object based on the received vertex buffer data and texture data and completes the rendering.
[0393] In summary, the tile rendering method provided in this application belongs to the field of WebGIS electronic map technology and is applied to high-performance rendering scenarios of large-scale geospatial vector data in a WebGL environment. This application offloads all computationally intensive tasks such as vector feature data parsing, symbolization processing, overlay processing, resource data collection, texture atlas packaging, and vertex construction to sub-threads for execution. The main thread is only responsible for the final rendering object creation and rendering, thereby achieving high-performance, low-latency rendering of large-scale vector tile data.
[0394] Furthermore, the tile rendering method provided in this application has the following technical improvements:
[0395] (1) A coordinate quantization and offset stacking strategy is adopted to automatically process the overlap of icons and text of the same position point elements in the sub-thread through two traversals. This application uses coordinate quantization, offset and rotation angle to participate in the generation of unique keys, so that the elements of the same coordinate with different styles are offset independently, ensuring that the text label always follows the offset of the corresponding icon and that there is no separation of image and text.
[0396] (2) A dual-priority queue scheduling mechanism is adopted. All tile loading tasks corresponding to the same data source carry the same target sub-thread identifier to ensure thread affinity. When the data source worker in the sub-thread loads data for the first time, it caches feature data, spatial extent, and layer configuration. Subsequent tile loading tasks can directly use the cached spatial index to perform spatial queries without retransmitting and parsing the data source configuration, thus reducing the overhead of repeated data transmission and parsing.
[0397] (3) A dual-atlas strategy is adopted to place the icon image data in suitable available locations, and the atlas size grows dynamically. The icon image data of some builder objects may change dynamically at runtime. This application manages a dedicated texture atlas for these builder objects independently. When updating, only the texture atlas of the builder object itself needs to be repackaged, without affecting other builder objects. Builder objects with relatively stable resources share a single texture atlas, minimizing the number of texture bindings to the graphics processor. The texture atlas size grows dynamically according to the placed image blocks to avoid wasting space.
[0398] Furthermore, the tile rendering method provided in this application has the following technical effects:
[0399] (1) The main thread frame rate was increased from 15fps to 60fps, and there was no lag in user interaction (drag, zoom, click), achieving high-performance and low-latency rendering of large-scale vector tile data.
[0400] (2) The browser adopts a single main thread architecture, where JavaScript execution, DOM updates, CSS calculations, and WebGL rendering share the same main thread. This application moves the aforementioned computationally intensive tasks to a sub-thread, so the main thread only needs to perform approximately 2ms of rendering object creation and WebGL drawing calls per frame. The sub-thread is a browser background execution thread defined by the W3C HTML5 standard, running in parallel with the main thread and not blocking the user interface. This is the fundamental reason for achieving zero blocking on the main thread.
[0401] (3) Automatically solves the problem of overlapping icons and text of elements at the same location point without manual configuration. The offset is automatically stacked along the preset axis direction to ensure that each element is visually recognizable while maintaining the association between icons and text.
[0402] (4) By utilizing the cached data source state (feature data, spatial extent, layer configuration) of the sub-thread, the overhead of repeated data transmission and parsing is reduced, and the tile loading delay is reduced by about 40% under continuous scaling operations.
[0403] (5) Constructor objects with independent atlas requirements support dynamic updates at runtime, while other constructor objects share the texture atlas to reduce the number of texture bindings by the graphics processor and improve rendering performance. The dual atlas strategy takes into account both rendering flexibility and texture memory efficiency.
[0404] Figure 10 This is a schematic diagram of the structure of the tile rendering device provided in the embodiments of this application, as shown below. Figure 10 As shown, the tile rendering device 100 provided in this embodiment includes:
[0405] The sending module 1001 is used to send a tile loading task from the main thread to the child thread. The tile loading task carries an identifier of the target tile that needs to be loaded based on the current viewport.
[0406] The acquisition module 1002 is used to acquire the vector feature data corresponding to the tile loading task through a sub-thread in response to the tile loading task.
[0407] Processing module 1003 is used to perform symbolization processing on vector feature data through a sub-thread to generate a builder object for describing rendering styles;
[0408] Module 1004 is used to construct vertices based on the builder object through a sub-thread, generating vertex buffer data and texture data;
[0409] The sending module 1001 is also used to send vertex buffer data and texture data to the main thread via a sub-thread;
[0410] Create module 1005, which is used by the main thread to create a rendering object based on the received vertex buffer data and texture data, and add the rendering object to the rendering scene.
[0411] In one possible implementation, the processing module 1003 is specifically used for:
[0412] The sub-thread calls the renderer's symbol construction method based on the renderer configuration corresponding to the layer to which the vector feature data belongs;
[0413] Vector feature data is converted into multiple builder objects using a symbolic construction method;
[0414] Each builder object contains the type of the builder object, a list of feature data, and rendering style parameters.
[0415] In one possible implementation, module 1004 is specifically used for:
[0416] The child thread generates texture data based on the resource data required by the builder object;
[0417] For each builder object, vertex attribute data is generated based on texture data and written to the vertex buffer.
[0418] Group the builder objects written to the vertex buffer by layer name to obtain multiple builder object groups;
[0419] Each builder object group contains at least one builder object and a corresponding vertex buffer. The vertex buffer data includes each builder object in multiple builder object groups and its corresponding vertex buffer.
[0420] In one possible implementation, module 1005 is created, specifically for:
[0421] The main thread creates texture objects for the texture data;
[0422] A render object is created based on vertex buffer data and texture objects. The render object contains geometry and materials.
[0423] Add the rendered object to the corresponding layer of the rendered scene.
[0424] In one possible implementation, the sending module 1001 is specifically used for:
[0425] If the tile loading task carries the identifier of the target child thread, the main thread determines whether the number of tasks of the target child thread is less than the preset task limit.
[0426] If the value is less than the target value, the tile loading task will be dispatched to the target child thread.
[0427] If it is greater than or equal to, then add the tile loading task to the first queue;
[0428] If the tile loading task does not carry the identifier of the target child thread, then the tile loading task is added to the second queue;
[0429] The scheduling priority of the first queue is higher than that of the second queue, and the tile loading tasks corresponding to the same data source all carry the same target sub-thread identifier.
[0430] In one possible implementation, module 1004 is specifically used for:
[0431] The child thread sends resource requests to the main thread in parallel via reverse communication. The resource requests include at least one of image resource requests, glyph resource requests, and SVG resource requests.
[0432] The main thread responds to resource requests sent by the child thread, calls the corresponding resource manager in parallel to load the resources, and then sends the loaded resource data back to the child thread.
[0433] After obtaining all the resource data corresponding to the resource request, the child thread constructs vertices based on the builder object, generating vertex buffer data and texture data.
[0434] In one possible implementation, the tile rendering apparatus 100 further includes an offset module, which, after the sub-thread symbolizes the vector feature data and generates a builder object describing the rendering style, is used to:
[0435] The child thread quantizes the coordinates of point features in the builder object to a preset precision and generates position keys;
[0436] If there are other point features at the position corresponding to the position key, the point features are offset along the preset axis direction, and the offset amount is recorded.
[0437] Based on the offset, the corresponding point features in other builder objects associated with the point feature are offset along a preset axis direction.
[0438] In one possible implementation, after the sub-thread responds to the tile loading task and obtains the vector feature data corresponding to the tile loading task, the processing module 1003 is further configured to:
[0439] For point features with the tile limitation option enabled, the sub-thread determines whether the coordinates of the point feature are within the latitude and longitude range of the target tile; the tile limitation option is used to mark point features that need to perform tile boundary filtering.
[0440] If not, remove the point feature from the vector feature data.
[0441] The tile rendering device provided in this embodiment can execute the method provided in the above method embodiment. Its implementation principle and technical effect are similar, and will not be described in detail here.
[0442] Figure 11 This is a schematic diagram of the structure of an electronic device provided in an embodiment of this application. Figure 11 As shown, the electronic device 110 provided in this embodiment includes at least one processor 1101 and a memory 1102. Optionally, the electronic device 110 further includes a communication component 1103. The processor 1101, the memory 1102, and the communication component 1103 are connected via a bus 1104.
[0443] In a specific implementation, at least one processor 1101 executes computer execution instructions stored in memory 1102, causing at least one processor 1101 to perform the above-described method.
[0444] The specific implementation process of processor 1101 can be found in the above method embodiments, and its implementation principle and technical effect are similar. It will not be repeated here.
[0445] In the above embodiments, it should be understood that the processor can be a CPU, or other general-purpose processors, digital signal processors (DSPs), application-specific integrated circuits (ASICs), etc. The general-purpose processor can be a microprocessor or any conventional processor. The steps of the method disclosed in this invention can be directly implemented by a hardware processor, or implemented by a combination of hardware and software modules within the processor.
[0446] The memory may include random access memory (RAM) and may also include non-volatile memory (NVM), such as at least one disk storage device.
[0447] The bus can be an Industry Standard Architecture (ISA) bus, a Peripheral Component Interconnect (PCI) bus, or an Extended Industry Standard Architecture (EISA) bus, etc. Buses can be categorized as address buses, data buses, control buses, etc. For ease of illustration, the buses shown in the accompanying drawings are not limited to a single bus or a single type of bus.
[0448] This application also provides a computer program product, including a computer program that, when executed by a processor, implements the above-described method.
[0449] This application also provides a computer-readable storage medium storing computer-executable instructions, which, when executed by a processor, implement the above-described method.
[0450] The aforementioned readable storage medium can be implemented by any type of volatile or non-volatile storage device or a combination thereof, such as Static Random-Access Memory (SRAM), Electrically Erasable Programmable Read-Only Memory (EEPROM), Erasable Programmable Read-Only Memory (EPROM), Programmable Read-Only Memory (PROM), Read-Only Memory (ROM), magnetic storage, flash memory, magnetic disk, or optical disk. The readable storage medium can be any available medium accessible to a general-purpose or special-purpose computer.
[0451] An exemplary readable storage medium is coupled to a processor, enabling the processor to read information from and write information to the readable storage medium. Of course, the readable storage medium can also be a component of the processor. The processor and the readable storage medium can reside in an application-specific integrated circuit (ASIC). Alternatively, the processor and the readable storage medium can exist as discrete components in the device.
[0452] The division of units is merely a logical functional division; in actual implementation, there may be other division methods. For example, multiple units or components may be combined or integrated into another system, or some features may be ignored or not executed. Furthermore, the coupling or direct coupling or communication connection shown or discussed may be indirect coupling or communication connection through some interfaces, devices, or units, and may be electrical, mechanical, or other forms.
[0453] The units described as separate components may or may not be physically separate. The components shown as units may or may not be physical units; that is, they may be located in one place or distributed across multiple network units. Some or all of the units can be selected to achieve the purpose of this embodiment according to actual needs.
[0454] In addition, the functional units in the various embodiments of this application can be integrated into one processing unit, or each unit can exist physically separately, or two or more units can be integrated into one unit.
[0455] If a function is implemented as a software functional unit and sold or used as an independent product, it can be stored in a computer-readable storage medium. Based on this understanding, the technical solution of this application, in essence, or the part that contributes to the prior art, or a portion of the technical solution, can be embodied in the form of a software product. This computer software product is stored in a storage medium and includes several instructions to cause a computer device (which may be a personal computer, server, or network device, etc.) to execute all or part of the steps of the methods of the various embodiments of this application. The aforementioned storage medium includes various media capable of storing program code, such as USB flash drives, portable hard drives, ROM, RAM, magnetic disks, or optical disks.
[0456] Those skilled in the art will understand that all or part of the steps of the above-described method embodiments can be implemented by hardware related to program instructions. The aforementioned program can be stored in a computer-readable storage medium. When executed, the program performs the steps of the above-described method embodiments; and the aforementioned storage medium includes various media capable of storing program code, such as ROM, RAM, magnetic disks, or optical disks.
[0457] Finally, it should be noted that other embodiments of this application will readily conceive of by those skilled in the art upon consideration of the specification and practice of the invention disclosed herein. This application is intended to cover any variations, uses, or adaptations of this application that follow the general principles of this application and include common knowledge or customary techniques in the art not disclosed herein, and is not limited to the precise structures described above and shown in the accompanying drawings, and various modifications and changes may be made without departing from its scope.
Claims
1. A tile rendering method, characterized in that, Applied to electronic devices with a main thread and child threads, the method includes: The main thread sends a tile loading task to the child thread, and the tile loading task carries an identifier of the target tile that needs to be loaded based on the current viewport. The sub-thread responds to the tile loading task and obtains the vector feature data corresponding to the tile loading task; The sub-thread performs symbolization processing on the vector feature data to generate a builder object for describing the rendering style; The sub-thread constructs vertices based on the builder object, generating vertex buffer data and texture data; The sub-thread sends the vertex buffer data and the texture data to the main thread; The main thread creates a rendering object based on the received vertex buffer data and texture data, and adds the rendering object to the rendering scene.
2. The method according to claim 1, characterized in that, The sub-thread performs symbolization processing on the vector feature data to generate a builder object for describing the rendering style, including: The sub-thread calls the renderer's symbol construction method according to the renderer configuration corresponding to the layer to which the vector feature data belongs; The symbol construction method is used to convert the vector feature data into multiple builder objects; Each builder object contains the type of the builder object, a list of feature data, and rendering style parameters.
3. The method according to claim 1, characterized in that, The sub-thread constructs vertices based on the builder object, generating vertex buffer data and texture data, including: The sub-thread generates the texture data based on the resource data required by the builder object; For each builder object, vertex attribute data is generated based on the texture data and written to the vertex buffer. Group the builder objects written to the vertex buffer by layer name to obtain multiple builder object groups; Each builder object group contains at least one builder object and a corresponding vertex buffer, wherein the vertex buffer data includes each builder object in the plurality of builder object groups and the corresponding vertex buffer.
4. The method according to any one of claims 1-3, characterized in that, The main thread creates a rendering object based on the received vertex buffer data and texture data, and adds the rendering object to the rendering scene, including: The main thread creates a texture object for the texture data; A rendering object is created based on the vertex buffer data and the texture object, the rendering object containing geometry and materials; Add the rendered object to the corresponding layer of the rendered scene.
5. The method according to any one of claims 1-3, characterized in that, The main thread sends a tile loading task to the child thread, including: If the tile loading task carries the identifier of the target sub-thread, the main thread determines whether the number of tasks of the target sub-thread is less than the preset task quantity limit; If the value is less than the target value, the tile loading task will be distributed to the target sub-thread. If the value is greater than or equal to the value, the tile loading task is added to the first queue. If the tile loading task does not carry the identifier of the target sub-thread, then the tile loading task is added to the second queue; The scheduling priority of the first queue is higher than that of the second queue, and the tile loading tasks corresponding to the same data source all carry the same target sub-thread identifier.
6. The method according to any one of claims 1-3, characterized in that, The sub-thread constructs vertices based on the builder object, generating vertex buffer data and texture data, including: The sub-thread sends resource requests to the main thread in parallel via reverse communication. The resource requests include at least one of image resource requests, font resource requests, and scalable vector graphics (SVG) resource requests. The main thread responds to the resource request sent by the child thread, calls the corresponding resource manager in parallel to load the resource, and sends the loaded resource data back to the child thread; After obtaining all the resource data corresponding to the resource request, the sub-thread constructs vertices based on the builder object, generating vertex buffer data and texture data.
7. The method according to any one of claims 1-3, characterized in that, After the sub-thread performs symbolization processing on the vector feature data to generate a builder object for describing the rendering style, the method further includes: The sub-thread quantizes the coordinates of point features in the builder object to a preset precision and generates a position key; If there are other point elements at the position corresponding to the position key, the point element is offset along the preset axis direction, and the offset amount is recorded. Based on the offset, the corresponding point features in other builder objects associated with the point feature are offset along the preset axis direction.
8. The method according to any one of claims 1-3, characterized in that, After the sub-thread responds to the tile loading task and obtains the vector feature data corresponding to the tile loading task, the method further includes: For point features with the tile restriction option enabled, the sub-thread determines whether the coordinates of the point feature are within the latitude and longitude range of the target tile; wherein, the tile restriction option is used to mark point features that need to perform tile boundary filtering; If not, then remove the point feature from the vector feature data.
9. A tile rendering device, characterized in that, An electronic device having a main thread and child threads deployed thereon, the device comprising: The sending module is used to send a tile loading task to the child thread through the main thread. The tile loading task carries an identifier of the target tile that needs to be loaded based on the current viewport. The acquisition module is used to acquire vector feature data corresponding to the tile loading task in response to the tile loading task via the sub-thread; The processing module is used to perform symbolization processing on the vector feature data through the sub-thread to generate a builder object for describing the rendering style; The construction module is used to construct vertices based on the builder object through the sub-thread, and generate vertex buffer data and texture data; The sending module is further configured to send the vertex buffer data and the texture data to the main thread through the sub-thread; A creation module is used to create a rendering object based on the received vertex buffer data and texture data through the main thread, and add the rendering object to the rendering scene.
10. An electronic device / computer-readable storage medium / computer program product, characterized in that, The electronic device includes: a memory and a processor; The memory stores computer-executed instructions; The processor executes computer execution instructions stored in the memory, causing the processor to perform the method as described in any one of claims 1-8; The computer-readable storage medium stores computer-executable instructions, which, when executed by a processor, are used to implement the method as described in any one of claims 1-8; The computer program product includes a computer program that, when executed by a processor, implements the method described in any one of claims 1-8.
