views:

26

answers:

2

Hi All,

I have a set of points to define a shape. These points are in order and essentially are my "selection".

I want to be able to contract this selection by an arbitrary amount to get a smaller version of my original shape.

In a basic example with a triangle, the points are simply moved along their normal which is defined by the points to the left and the right of the points in question.

Eventually all 3 points will meet and form one point but until that point they will make a smaller and smaller triangle.

For more complex shapes, when moving the individual points inward, they may pass through the outer edge of the shape resulting in weird artifacts. Obviously I'll need to cull these points and remove them from the array.

Any help in exactly how I can do that would be greatly appreciated.

Thanks!

+1  A: 

This is just an idea but couldn't you find the center of mass of the object, create a vector from the center to each point, and move each point along this vector?

To find the center of mass would of course involve averaging each x and y coordinate. Getting a vector is as simple a subtracting the point in question with the center point. Normalizing and scaling are common vector operations that can be found with the Google.

EDIT
Another way to interpret what you're asking is you want to erode your collection of points. As in morphology erosion. This is typically applied to binary images but you can slightly modify the concept to work with a collection of points. Essentially, you need to write a function that, given a point, will return true (black) or false (white) depending on if that point is inside or outside the shape defined by your points. You'd have to look up how to do that for shapes that aren't always concave (it's harder but not impossible).

Now, obviously, every single one of your actual points will return false because they're all on the border (by definition). However, you now have a matrix of points around your point of interest that define where is "inside" and where is "outside". Average all of the "inside" points and move your actual point along the vector between itself and towards this average. You could play with different erosion kernels to see what works best.

You could even work with a kernel with floating point weights instead of either/or values which will affect your average calculation proportional to their weights. With this, you could approximate a circular kernel with a low number of points. Try the simpler method first.

colithium
The issue with scaling towards center of mass is that the contour of the edge of the shape isn't preserved. You can see the results in photoshop or flash etc. Create a irregular shape with a paint brush in one color. Then duplicate the same shape with another color and layer the two on top. Now start scaling one to be smaller. The shapes look identical, but the edges will overlap in areas instead of a uniform contraction of the outer edge. Thanks anyway though.
Jon
See my edit to see if I understand you now
colithium
Hey colithium, Yep, erosion is what I was looking for. I haven't had the time to fully explore and implement it, but this is what i'll need to do. Thanks again!
Jon
A: 
  1. Find the selection center (as suggested by colithium)
  2. Map the selection points to the coordinate system with the selection center at (0,0). For example, if the selection center is at (150,150), and a given selection point is at (125,75), the mapped position of the point becomes (-25,-75).
  3. Scale the mapped points (multiply X and Y by something in the range of 0.0..1.0)
  4. Remap the points back to the original coordinate system

Only simple maths required, no need to muck about normalizing vectors.

allonym
This has a huge disadvantage - outer points will move by more than inner ones. I don't think it meets the description of the problem as given.
Mark Ransom
excellent point.
allonym
Yeah unfortunately this won't work but I appreciate the reply.
Jon