Drawing image with origin offset based on polygon shape - a bit of mismatch

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
dusoft
Party member
Posts: 765
Joined: Fri Nov 08, 2013 12:07 am
Location: Europe usually
Contact:

Drawing image with origin offset based on polygon shape - a bit of mismatch

Post by dusoft »

Hello,

I have searched the forums (and read the wiki) and applied origin offset to drawing images matching physics polygon shapes as such:

Code: Select all

-- base_fixture is my fixture to draw
        local x, y = objects.getCentroid({base_fixture:getBody():getWorldPoints(base_fixture:getShape():getPoints())})
        local offset_x = base_fixture:getUserData().image[1]:getWidth() / 2
        local offset_y = base_fixture:getUserData().image[1]:getHeight() / 2
        local scale = 0.05
        love.graphics.setColor(love.math.colorFromBytes(255, 255, 255))
        love.graphics.draw(base_fixture:getUserData().image[1], x, y, base_fixture:getBody():getAngle(), scale, scale, offset_x, offset_y)
        
However I still see mismatch between the actual polygon shape and image drawn - image is drawn a few Y points above the correct position of polygon shape.

See the attached image - polygon shaped is filled with red color, image is drawn over it and positions do not match. If I change the scale, the mismatch also seem to change.
Attachments
Screenshot_20250204_121213.png
Screenshot_20250204_121213.png (16.76 KiB) Viewed 2940 times
User avatar
dusoft
Party member
Posts: 765
Joined: Fri Nov 08, 2013 12:07 am
Location: Europe usually
Contact:

Re: Drawing image with origin offset based on polygon shape - a bit of mismatch

Post by dusoft »

Once again, I tried drawing without scaling neither the image, nor the polygon and I get this (arrows where image starts and ends, polygon drawn as a dark red outline):
offset.png
offset.png (187.21 KiB) Viewed 2764 times
The polygon vertices are traced from the image visually, so I can vouch for correctness of the data.

Could it be that the x,y coordinates I am using to draw the polygon (love.physics fixture) are incorrect due to using the getCentroid function?

Code: Select all

local x, y = objects.getCentroid({base_fixture:getBody():getWorldPoints(base_fixture:getShape():getPoints())})
        local offset_x = base_fixture:getUserData().image[1]:getWidth() / 2
        local offset_y = base_fixture:getUserData().image[1]:getHeight() / 2
        
the function (seems to be working alright for other use):

Code: Select all

function objects.getCentroid(vertices)
    local sum_x, sum_y = 0, 0
    for i = 1, #vertices, 2 do
        sum_x = sum_x + vertices[i]
        sum_y = sum_y + vertices[i + 1]
    end
    local cx, cy = math.round(sum_x / (#vertices / 2)), math.round(sum_y / (#vertices / 2))
    return cx, cy
end
RNavega
Party member
Posts: 456
Joined: Sun Aug 16, 2020 1:28 pm

Re: Drawing image with origin offset based on polygon shape - a bit of mismatch

Post by RNavega »

Hi, have you tried plotting the points involved, that is the centroid and the image center? I do think the centers are mismatched.

With (width / 2) and (height / 2) you're getting the bounding box center, which is one thing.
With sum_x and sum_y divided by the number of vertices (not half the vertices, by the way), you're getting a mean or average of the location of all vertices, and this has a quirk where it tends to gravitate towards clusters of vertices, instead of being a balanced point.

For an extreme example, imagine a shape where you have hundreds of vertices close together and just one single vertex far away: the average point will be almost centered on those tightly grouped vertices, whereas the bounding-box center will be balanced over the entire shape including that single far away vertex.
User avatar
dusoft
Party member
Posts: 765
Joined: Fri Nov 08, 2013 12:07 am
Location: Europe usually
Contact:

Re: Drawing image with origin offset based on polygon shape - a bit of mismatch

Post by dusoft »

Thanks, @RNavega, I suspected so at the end, but I am going to investigate further this weekend with your helpful comment.
RNavega
Party member
Posts: 456
Joined: Sun Aug 16, 2020 1:28 pm

Re: Drawing image with origin offset based on polygon shape - a bit of mismatch

Post by RNavega »

Good luck. There seem to be some bounding box helper functions that could be useful in your case:
https://love2d.org/wiki/Shape:getBoundingBox
https://love2d.org/wiki/Fixture:getBoundingBox

I don't know if the returned B.B. points are already rotated based on the body angle (easy to test by plotting them on screen).

If they're not rotated then you can use a Transform object and :transformPoint(), or manually rotate them with a 2D affine transform, then finally find the center of that rotated B.B.
User avatar
pgimeno
Party member
Posts: 3709
Joined: Sun Oct 18, 2015 2:58 pm

Re: Drawing image with origin offset based on polygon shape - a bit of mismatch

Post by pgimeno »

By the way, here's how to actually calculate the centroid of a polygon:

https://en.wikipedia.org/wiki/Centroid#Of_a_polygon

What I fail to understand, however, is why not to use Body:getPosition().
User avatar
dusoft
Party member
Posts: 765
Joined: Fri Nov 08, 2013 12:07 am
Location: Europe usually
Contact:

Re: Drawing image with origin offset based on polygon shape - a bit of mismatch

Post by dusoft »

I have changed coordinates to draw the image over polygon shape to those received from a bounding box, i.e.:

Code: Select all

local topleft_x, topleft_y, bottomleft_x, bottomleft_y = fixture:getBoundingBox()
            local x, y = topleft_x + (bottomleft_x - topleft_x) / 2, topleft_y + (bottomleft_y - topleft_y) / 2
            local w = fixture:getUserData().image[1]:getWidth()
            local h = fixture:getUserData().image[1]:getHeight()
            local scale = 0.05
            love.graphics.setColor(love.math.colorFromBytes(255, 255, 255))
            love.graphics.draw(fixture:getUserData().image[1], x, y, fixture:getBody():getAngle(), scale, scale, w / 2, h / 2)
It seems to be working better, but only for some angles (e.g. 0, 90, 180, 270 degrees), but for others between there is still an inconsistency. Do I need to compensate position for an angle somehow as well?

See different angles vs image/polygon outline:
1.png
1.png (5.47 KiB) Viewed 1500 times
2.png
2.png (7.16 KiB) Viewed 1500 times
3.png
3.png (7.52 KiB) Viewed 1500 times
4.png
4.png (6 KiB) Viewed 1500 times
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Amazon [Bot], Google [Bot], Semrush [Bot] and 4 guests