You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

加速曲线网格到矩形网格插值的点所属单元查找

提升曲线网格到规则网格的点归属查找效率问题

我正尝试搭建一套从曲线网格到规则网格的点插值方法,核心需求是确定规则网格的每个点所属的曲线网格单元(曲线网格单元为随机四边形)。

网格创建示例(含不利场景)

import numpy as np
import matplotlib.pyplot as plt

def circle(xn, yn):
    """Polar grid."""
    R = (xn[-1, 0] - xn[0, 0]) / (2*np.pi)
    return (yn + R)*np.sin(xn/R), (yn + R)*np.cos(xn/R)


_x= np.linspace(0, 0.1, 150)
_y = np.linspace(0, 0.1, 100)

# Curvilinear grid
up, vp = circle(np.meshgrid(_x, _y, indexing='ij'))

# Cartesian grid
ui = np.linspace(up.min(), up.max(), 300)
vi = np.linspace(vp.min(), vp.max(), 200)

现有四边形点查找算法

我已通过经典四边形点查找算法实现网格间的对应关系:

%%cython -f -c=-O2 -I./ --compile-args=-fopenmp --link-args=-fopenmp

cimport cython
from cython.parallel cimport prange
import numpy as np
cimport numpy as np


@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
cpdef neighbors(double[:, ::1] xp, double[:, ::1] yp, double xi, double yi):
    """Clockwise winding Polygon :

        [[xp[ix, iy], yp[ix, iy]],
         [xp[ix, iy+1], yp[ix, iy+1]],
         [xp[ix+1, iy+1], yp[ix+1, iy+1]],
         [xp[ix+1, iy], yp[ix+1, iy]]])
    """
    cdef Py_ssize_t nx = xp.shape[0]
    cdef Py_ssize_t ny = xp.shape[1]
    cdef Py_ssize_t ix, iy = 0
    cdef Py_ssize_t tag = 0
    cdef double xmin, xmax, ymin, ymax
    cdef double x1, x2, x3, x4, y1, y2, y3, y4

    for ix in range(nx-1):

        for iy in range(ny-1):

            x1 = xp[ix, iy]
            x2 = xp[ix, iy+1]
            x3 = xp[ix+1, iy+1]
            x4 = xp[ix+1, iy]
            y1 = yp[ix, iy]
            y2 = yp[ix, iy+1]
            y3 = yp[ix+1, iy+1]
            y4 = yp[ix+1, iy]

            if xi - min(x1, x2, x3, x4) < 0.:
                continue

            if yi - min(y1, y2, y3, y4) < 0.:
                continue
            
            # Check that point (xi, yi) is on the same side of each edge of the quadrilateral
            if not (xi - x1) * (y2 - y1) - (x2 - x1) * (yi - y1) > 0:
                continue
            if not (xi - x2) * (y3 - y2) - (x3 - x2) * (yi - y2) > 0:
                continue
            if not (xi - x3) * (y4 - y3) - (x4 - x3) * (yi - y3) > 0 :
                continue
            if not (xi - x4) * (y1 - y4) - (x1 - x4) * (yi - y4) > 0:
                continue

            tag = 1
            break
        if tag == 1:
            break
    if tag == 1:
        return (ix, iy), (ix, iy+1), (ix+1, iy+1), (ix+1, iy)
    return None

算法运行验证

该算法可正常运行:

fig, axes = plt.subplots(1, 1, figsize=(6, 6))

for i in np.arange(0, ui.shape[0]):
    axes.axvline(ui[i], color='k', linewidth=0.1)
for i in np.arange(0, vi.shape[0]):
    axes.axhline(vi[i], color='k', linewidth=0.1)

for i in np.arange(0, vp.shape[1]):
    axes.plot(up[:, i], vp[:, i], 'k', linewidth=0.5)
for i in np.arange(0, up.shape[0]):
    axes.plot(up[i, :], vp[i, :], 'k', linewidth=0.5)

for iu, iv in ((180, 120), (100, 90), (80, 40), (10, 10)):
    axes.plot(ui[iu], vi[iv], 'ro')
    idx = neighbors(up, vp, ui[iu], vi[iv])
    if idx:
        for _idx in idx:
            axes.plot(up[_idx], vp[_idx], 'go')
plt.show()

性能瓶颈说明

但当前效率过低:在我的系统中,该网格下每个点查找平均耗时15微秒,2000×2000网格的单点查找耗时7毫秒,若查找2000×2000个点,预估总耗时达28000秒,3D场景耗时更甚。

我认为可通过跳过曲线网格外的点来节省时间,但暂无简单判断指标;同时推测存在更优的全局查找方法,但尚不了解。

尝试的二分法优化及问题

我尝试通过针对x轴的二分法来大幅缩短计算时间,但如下代码在x非单调时会出现错误:

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
cpdef bint is_monotonic(double[:, ::1] v):
    cdef Py_ssize_t i

    for i in range(v.shape[0] - 1):
        if (v[i, 1] > v[i, 0]) != (v[i+1, 1] > v[i+1, 0]):
            return False
    return True


@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
cpdef (double, double) minmax(double[:] arr):
    cdef double min = arr[0]
    cdef double max = arr[0]
    cdef Py_ssize_t i
    cdef Py_ssize_t n = arr.shape[0]

    for i in range(1, n):
        if arr[i] < min:
            min = arr[i]
        elif arr[i] > max:
            max = arr[i]
    return min, max


@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
cpdef (Py_ssize_t, Py_ssize_t) dichotomy(double[:, ::1] xp, double xi, Py_ssize_t offset=1):

    cdef Py_ssize_t nx = xp.shape[0]
    cdef Py_ssize_t istart = 0
    cdef Py_ssize_t istop = nx - 1
    cdef Py_ssize_t middle = (istart + istop) // 2
    cdef double xmin1, xmin2, xmax1, xmax2
    cdef double xmin, xmax


    while (istop - istart) > 3:

        middle = (istart + istop) // 2

        xmin1, xmax1 = minmax(xp[istart, :])
        xmin2, xmax2 = minmax(xp[middle, :])
        xmin = min(xmin1, xmax1, xmin2, xmax2)
        xmax = max(xmin1, xmax1, xmin2, xmax2)

        if xmin <= xi <= xmax:
            if middle - istart < 3:
                return istart - offset, middle + offset
            istop = middle
        else:
            istart = middle

    xmin1, xmax1 = minmax(xp[middle, :])
    xmin2, xmax2 = minmax(xp[istop, :])
    xmin = min(xmin1, xmax1, xmin2, xmax2)
    xmax = max(xmin1, xmax1, xmin2, xmax2)

    if xmin <= xi <= xmax:
        return middle - offset, istop + offset
    return -1, -1

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
cpdef neighbor(double[:, ::1] xp, double[:, ::1] yp, double xi, double yi):

    (...)

    cdef Py_ssize_t istart = 0
    cdef Py_ssize_t istop = nx - 2

    if is_monotonic(xp):
        istart, istop = dichotomy(xp, xi)
        if istart == -1:
            return None

    for ix in range(istart, istop + 1):
        for iy in range(ny-1):
            (...)

咨询问题

如何借助Cython/Numpy提升该点所属单元查找的效率?


内容的提问来源于stack exchange,提问作者Ipse Lium

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 00:44:56