luageometrycurvelove2d

Polyline curvature in Lua, Love2D


I have a polyline (white) with coordinates {x1, y1, x2, y2, x3, y3 ...}

polyline = {100,300,160,257,220,242,280,250,340,271,400,300,460,329,520,350,580,358,640,343,700,300}

How can I get the curvature of it? The result must be same as the curvature of Bezier (red curve on the calculated heights):

curve and bezier curvature

I can understand, that the ends of polyline must have the zero curvature.

The result must be something like:

curve and bezier curvature and polyline curvature


Solution

  • Here was the solution: Determining curvature of polylines

    -- function to calculate the curvature of a polyline segment using three points
    local function calculatePolylineCurvature(p1x, p1y, p2x, p2y, p3x, p3y)
    --  https://gis.stackexchange.com/questions/195370/determining-curvature-of-polylines
        -- compute the determinant (signed area of the triangle)
        local numerator = 2 * ((p2x - p1x) * (p3y - p2y) - (p2y - p1y) * (p3x - p2x))
    
        -- compute the product of the three segment lengths
        local len1 = (p2x - p1x)^2 + (p2y - p1y)^2
        local len2 = (p3x - p2x)^2 + (p3y - p2y)^2
        local len3 = (p1x - p3x)^2 + (p1y - p3y)^2
    
        local denominator = math.sqrt(len1 * len2 * len3)
    
        -- prevent division by zero
        if denominator == 0 then
            return nil
        end
        return -8.1*numerator / denominator -- just to set the same scale as Bezier curvature
    end
    
    -- function to calculate the normal vector to the polyline segment
    local function calculatePolylineNormal(p1x, p1y, p2x, p2y, p3x, p3y)
        return p1y - p3y, p3x - p1x
    end
    

    The main function:

        polyline = {100,300,160,257,220,242,280,250,340,271,400,300,460,329,520,350,580,358,640,343,700,300}
    
        local length = 20
        polylineCurvatureLines = {}
        polylineCurvatureHeightLine = {}
    
        table.insert (polylineCurvatureHeightLine, polyline[1])
        table.insert (polylineCurvatureHeightLine, polyline[2])
    
        for i = 3, #polyline - 3, 2 do
            local p1x, p1y = polyline[i-2], polyline[i-1]
            local p2x, p2y = polyline[i], polyline[i+1]
            local p3x, p3y = polyline[i+2], polyline[i+3]
    
            local k = calculatePolylineCurvature(p1x, p1y, p2x, p2y, p3x, p3y)
            local nx, ny = calculatePolylineNormal (p1x, p1y, p2x, p2y, p3x, p3y)
    
            nx = nx * k * length
            ny = ny * k * length
    
            table.insert (polylineCurvatureLines, {p2x, p2y, p2x + nx, p2y + ny})
            table.insert (polylineCurvatureHeightLine, p2x + nx)
            table.insert (polylineCurvatureHeightLine, p2y + ny)
        end
    
        table.insert (polylineCurvatureHeightLine, polyline[#polyline-1])
        table.insert (polylineCurvatureHeightLine, polyline[#polyline])
    

    The result:

    good polyline curvature

    Update:

    It has a mistake! The curvature will be lower for more curve divisions!