Visio Guy

Visio Discussions => Programming & Code => Topic started by: bwharrington on August 08, 2019, 02:04:11 PM

Title: Fitting n shapes of size n x m into a container size n.
Post by: bwharrington on August 08, 2019, 02:04:11 PM
I have a problem that I do not believe is terribly unique and I wonder if this has been solved and may be laying around out there.

As the title suggests,

1 - I have n shapes in a container
2 - The shapes have a fixed size of 1 x 1 to start.
3 - The  container is size n x m. Any size really.

I need to place all of the size from left to right in a row/column format in order to take up as much of the space as I can. Resizing the shapes to fit. The last row can have a minimum of 1 shape in it.

Has this been solved or possibly a similar solution with some tweaking might get me there? I figure I would spend some time searching rather than reinvent the wheel here.

Thanks,
Title: Re: Fitting n shapes of size n x m into a container size n.
Post by: wapperdude on August 08, 2019, 02:23:25 PM
Take a look at this thread:  http://visguy.com/vgforum/index.php?topic=6563.msg27718#msg27718 (http://visguy.com/vgforum/index.php?topic=6563.msg27718#msg27718)
Title: Re: Fitting n shapes of size n x m into a container size n.
Post by: Yacine on August 09, 2019, 10:49:35 AM
Hello bw,The post Wapperdude is referring to is for a real bin stacking problem. Quite challenging for us "simple" visio guys. s. attached sketch of such an exercise.

Your question if I take literally is simple.
n shapes in a container n x m will be placed in exactly one row. (m-1) x n space will remain free.

But, I believe you just formulated the question inaccurately.

You probably meant:
The shapes are squares of side b
The are x shapes
The container's dimensions are n x m

In this case the position of a shape shp_i would be:
shp_i.x = i modulo (m/b) * b
shp_i.y = floor(i / (m/b) ) * b

You may look at the following posts for automation:
- Thomas Winkel: http://visguy.com/vgforum/index.php?topic=4927.0- (http://visguy.com/vgforum/index.php?topic=4927.0-)
- Shapes relations tool: http://visguy.com/vgforum/index.php?topic=6914.15 (http://visguy.com/vgforum/index.php?topic=6914.15)

Title: Re: Fitting n shapes of size n x m into a container size n.
Post by: bwharrington on August 14, 2019, 01:29:15 PM
Thanks Yacine,

I apologize for not getting back sooner. I really appreciate the effort you have put into my post and the other post I reviewed of yours for us mortal individuals :).

I've been attempting to tweak what you have provided to more accurately fit my scenario. Your summation of what I need to do its pretty accurate but I posted an image of what I am trying to do.

So far I have taken your idea and put it into code.

What I am finding is the shapes are stacking from left to right, bottom up and in relation to the page instead of the container. I've been trying to manipulate this in such a way that it going from left to right, top down starting in the container with a 3mm margin.

I'm going to continue tinkering with this. One advantage I do have is that the shape size can be reduced or increased as desired.

Code
var shapeWidth = componentStyle == ComponentStyle.Modern ? VisioConstants.MODERN_SHAPE_WIDTH : VisioConstants.CLASSIC_SHAPE_WIDTH;
var shapeHeight = componentStyle == ComponentStyle.Modern ? VisioConstants.MODERN_SHAPE_HEIGHT : VisioConstants.CLASSIC_SHAPE_HEIGHT;

var containerShapeIds = container.ContainerProperties.GetMemberShapes((int)VisContainerFlags.visContainerFlagsDefault);
var sortedDictionary = VisioHelper.CreateAndSortShapeDictionary(_application, containerShapeIds);

decimal containerWidth = (decimal)container.GetMeasuredValue("Width", VisUnitCodes.visInches);
decimal containerHeight = (decimal)container.GetMeasuredValue("Height", VisUnitCodes.visInches);

int i = 0;
foreach (var shape in sortedDictionary)
{
    var shapeX = i % ((double)containerWidth / shapeWidth) * shapeWidth;
    var shapeY = Math.Floor(i / (double)containerWidth / shapeWidth) * shapeWidth;
    var containedShape = _application.ActivePage.Shapes.ItemFromID[shape.Key];
    containedShape.SetPin(shapeX, shapeY);
    i++;
}

Title: Re: Fitting n shapes of size n x m into a container size n.
Post by: Yacine on August 15, 2019, 12:24:53 AM
Your code looks good so far.
It seems the last point left is to invert the vertical order.
Instead of y = floor(i / (m/b) ) * b
you would write y = container.piny - floor(i / (m/b) ) * b

Note that it would simplify your work if set locpiny to height*1 and locpinx to width*0. So you won't have to care about the height and the width when placing the images.

Rgds,
Y.
Title: Re: Fitting n shapes of size n x m into a container size n.
Post by: bwharrington on August 19, 2019, 11:48:38 AM
Thanks Yacine,

I think this got me where I needed to be. Your formulas are exactly what I needed to get the ball rolling.
Title: Re: Fitting n shapes of size n x m into a container size n.
Post by: maclarkson on September 04, 2019, 04:13:22 PM
Hay BW, did you programmatically create your own container, this look like something I could use if so?
Title: Re: Fitting n shapes of size n x m into a container size n.
Post by: wapperdude on September 04, 2019, 05:37:30 PM
@ maclarkson:  have you looked at this post, Of Containers and Lists, http://visguy.com/vgforum/index.php?topic=8697.0 (http://visguy.com/vgforum/index.php?topic=8697.0)?

Couple of Visio files and useful links.
Title: Re: Fitting n shapes of size n x m into a container size n.
Post by: bwharrington on November 20, 2019, 09:25:40 AM
@maclarkson

I apologize for not seeing this sooner. I did not create my own container. I use the native visio container functionality.