Shape detecting system?

anyone have an idea to how i can make a shape autocorrecting system? so the script would detect something like this and know that it is supposed to be a circle? I’m not asking to be spoonfed scripts, more just somebody to put me in the right direction.
image

2 Likes

There are a few options, the two I can think of off the top of my head are neural networks and static shape recognition.

The first one you can find plenty of tutorials online for, but you’ll have to find one that doesn’t rely on a complicated library and that does it from scratch.

For the second one, the idea is simple - assuming we are working with a drawn line - you simply go through each shape that you support, match its width/height to that of the fully drawn line (in this case the circle you provided is roughly 1:1), then determine for every X point on your line how close it is to X point on your shapes outline. The best/closest shape is what you would correct to. Of course you would only correct if it matches Y% or greater

Interesting question, but before that please move this topic to #help-and-feedback:scripting-support to prevent any moderator action against this post.

Anyways, the idea I feel like could work is to make some template shapes and then iterate over both the shapes and find the distance between each element, basically compare the 2 shapes, after this store that date in a table and move on with the next template, if the new template is more accurate than the previous one then set it as a refrence point. Repeat this for all templates until you have found the closest matched one. And that could be a way. It’s not really that easy so would take quite some brain power and time.

Get all of the angles of the items, put them in a table, then use table.sort and somehow configure all of the different angles to mean different things.

Script below (not mine), assuming that points is an array of 2D points (gl trying to guess the shape in 3D, just remove the Y coordinate since they’re all on one surface anyways.)

-- Function to determine the shape from a list of points
function determineShape(points)
    local numPoints = #points

    -- A shape must have at least 3 points
    if numPoints < 3 then
        return "Not enough points"
    end

    -- Check if all points are on a straight line
    local x1, y1 = points[1][1], points[1][2]
    local x2, y2 = points[2][1], points[2][2]
    local slope = (y2 - y1) / (x2 - x1)
    local isStraightLine = true

    for i = 3, numPoints do
        local x3, y3 = points[i][1], points[i][2]
        local currentSlope = (y3 - y1) / (x3 - x1)
        if currentSlope ~= slope then
            isStraightLine = false
            break
        end
    end

    if isStraightLine then
        return "Line"
    end

    -- Check if all points are equidistant from a center point (circle)
    local center = {x = 0, y = 0}
    for _, point in ipairs(points) do
        center.x = center.x + point[1]
        center.y = center.y + point[2]
    end
    center.x = center.x / numPoints
    center.y = center.y / numPoints

    local radiusSq = 0
    for _, point in ipairs(points) do
        local dx = point[1] - center.x
        local dy = point[2] - center.y
        radiusSq = radiusSq + dx * dx + dy * dy
    end

    local isCircle = true
    local tolerance = 0.1 -- Tolerance to account for floating-point precision errors
    for _, point in ipairs(points) do
        local dx = point[1] - center.x
        local dy = point[2] - center.y
        local distanceSq = dx * dx + dy * dy
        if math.abs(distanceSq - radiusSq) > tolerance then
            isCircle = false
            break
        end
    end

    if isCircle then
        return "Circle"
    end

    -- If it's not a line or circle, assume it's a polygon
    return "Polygon"
end

-- Example usage
local points = {{0, 0}, {1, 1}, {2, 0}} -- Example points
local shape = determineShape(points)
print("Shape:", shape)

If this is only meant to autocorrect regular polygons, measuring for abrupt changes in angles should be a valid solution. If you have all the points in the order of their placement, you can keep track of changes in degrees.

If you’ve got X points with only 3 major changes in angles, this is a triangle. Similarly, if you detect 4, 5, 6, 7 abrupt changes in angles, as long as we’re drawing regular polygons, these are likely squares, pentagons, hexagons, and heptagons respectively.

Depending on OP’s usecase this could be a fairly decent option; you could improve the polygon return accuracy by using something like the Ramer-Douglas-Peucker Algorithm. Once you decimate the curve you could count the number of remaining edges to det. whether it’s a triangle, rect etc +/- checking to see if the points meet other rules e.g. approximately 4x 90deg corners for a square/rectangle etc.

Not sure what your exact use case is here, OP, but if you’re doing this for some drawing-like game then you may want to take a look at other techniques as well e.g. the Hough transform for image feature extraction.

1 Like

Try detecting the amount of segments and their rotation from the previous one added and check if it’s roughly around 360 degrees, 4 segments would be a square, 16 would be a circle.

I could see this working, i’ll try it and get back to you