From 0e23945be461d2cfcb9f69b56c57f44fce102cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Tue, 7 Nov 2017 14:12:54 +0100 Subject: [PATCH] replace trimesh.triangulate_polygon with faster direct meshpy implementation --- src/c3nav/mapdata/render/engines/opengl.py | 36 ++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/c3nav/mapdata/render/engines/opengl.py b/src/c3nav/mapdata/render/engines/opengl.py index 1037f952..9c30f029 100644 --- a/src/c3nav/mapdata/render/engines/opengl.py +++ b/src/c3nav/mapdata/render/engines/opengl.py @@ -1,14 +1,15 @@ import io from collections import deque +from functools import lru_cache from itertools import chain from typing import Optional, Union +import meshpy.triangle as triangle import ModernGL import numpy as np from PIL import Image from shapely.geometry import CAP_STYLE, JOIN_STYLE, MultiPolygon, Polygon from shapely.ops import unary_union -from trimesh.creation import triangulate_polygon from c3nav.mapdata.render.engines.base import FillAttribs, RenderEngine, StrokeAttribs from c3nav.mapdata.utils.geometry import assert_multipolygon @@ -54,11 +55,42 @@ class OpenGLEngine(RenderEngine): self.np_scale = np.array((scale_x, -scale_y)) self.np_offset = np.array((-self.minx * scale_x - 1, self.maxy * scale_y - 1)) + @staticmethod + @lru_cache() + def get_face_indizes(start, length): + indices = np.tile(np.arange(start, start + length).reshape((-1, 1)), 2).flatten()[1:-1].reshape((length-1, 2)) + return np.vstack((indices, (indices[-1][-1], indices[0][0]))) + + @staticmethod + def triangulate_polygon(polygon): + vertices = deque() + faces = deque() + + offset = 0 + for ring in chain((polygon.exterior, ), polygon.interiors): + new_vertices = np.array(ring.coords)[:-1] + vertices.append(new_vertices) + faces.append(OpenGLEngine.get_face_indizes(offset, len(new_vertices))) + offset += len(new_vertices) + + holes = np.array(tuple( + Polygon(ring).representative_point().coords for ring in polygon.interiors + )) + + info = triangle.MeshInfo() + info.set_points(np.vstack(vertices)) + info.set_facets(np.vstack(faces).tolist()) + if holes.size: + info.set_holes(holes.reshape((holes.shape[0], -1))) + + mesh = triangle.build(info) + return np.array(mesh.points), np.array(mesh.elements) + def _create_geometry(self, geometry: Union[Polygon, MultiPolygon], append=None): triangles = deque() for i, polygon in enumerate(assert_multipolygon(geometry)): - vertices, faces = triangulate_polygon(polygon) + vertices, faces = self.triangulate_polygon(polygon) triangles.append(vertices[faces.flatten()]) vertices = np.vstack(triangles).astype(np.float32)