darkfrei
darkfrei

Reputation: 586

Polyline Curvature Combs 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

Upvotes: 1

Views: 47

Answers (1)

darkfrei
darkfrei

Reputation: 586

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!

  • factor = 20 for 40 crossings

    factor = 40 for 80 crossings

Upvotes: 1

Related Questions