473,387 Members | 1,456 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Arranging objects in a canvas like SQL Server

Hi,

I'm developing an mapping tool where the shapes are drawn in a canvas with
their related connections, Something like MS SQL server diagramming tool.

Now, I wish to provide an option (like sql server does: "Arrange tables") to
arrange all shapes so their connections so they can be shown in a beautifull
way. Can somebody suggest an alogorithm that will organize the shapes in
such a way that the endresult is clean?

Any help is appreciated.

Regards
Mar 13 '07 #1
1 1713
Here's some code I use to position shapes in a canvas.
Hope it helps you.

public class ShapePositioner
{
private float m_Width;
private SizeF m_Size;
private float m_Padding;

private List<Shapem_PositionedShapes = new List<Shape>();
ShapeLayoutGrid m_Grid;

public ShapePositioner(float width, SizeF shapeSize, float padding)
{
this.m_Width = width;
this.m_Size = shapeSize;
this.m_Padding = padding;
}

#region Public API

/// <summary>
/// Positions all of the shapes so that they do not obscure one another
/// </summary>
public void PositionShapes(List<AssignShapeshapes)
{
m_PositionedShapes.Clear();

// create a new grid
m_Grid = new ShapeLayoutGrid(m_Padding,
m_Size, m_Width);

// then position the shapes
foreach (Shape shape in shapes)
{

// find the next available location
Point position = FindNewLocation(0);
PositionShape(shape, position);

}
}

#endregion

#region Private Impl

/// <summary>
/// Positions the shape and marks the position off on the grid
/// </summary>
/// <param name="shape"></param>
/// <param name="location"></param>
private void PositionShape(Shape shape, Point location)
{
// mark the grid
m_Grid.MarkAsOccupied(location);
// extract the exact X and Y
PointF trueLocation = m_Grid.FindLocation(location);
// put the shape into that position
shape.Rectangle = new RectangleF(trueLocation, m_Size);
shape.X = trueLocation.X;
shape.Y = trueLocation.Y;
m_PositionedShapes.Add(shape);
}

/// <summary>
/// Finds the next empty location in the grid
/// starting from the row specified
/// </summary>
/// <param name="startingPoint"></param>
/// <param name="grid"></param>
/// <returns></returns>
private Point FindNewLocation(int startingRow)
{
int y = startingRow;
while (true)
{
for (int x = 0; x < m_Grid.ShapesPerRow; x++)
{
if (!m_Grid.IsPointOccupied(x, y))
{
return new Point(x, y);
}
}
y++;
}
}

#endregion
}

/// <summary>
/// Acts as a grid to position shapes and to record positions
/// where shapes have already been placed.
/// </summary>
public class ShapeLayoutGrid
{
#region Fields
private float m_Padding;
private SizeF m_ShapeSize;
private float m_GraphWidth;
private int[,] m_Grid;
private const int m_DefaultSize = 100;
#endregion

#region Ctor
/// <summary>
/// Ctor
/// </summary>
/// <param name="padding"></param>
/// <param name="shapeSize"></param>
/// <param name="graphWidth"></param>
/// <param name="numberOfShapes"></param>
public ShapeLayoutGrid(float padding, SizeF shapeSize, float graphWidth)
{
this.m_Padding = padding;
this.m_ShapeSize = shapeSize;
this.m_GraphWidth = graphWidth;
CalculateNewGrid(m_DefaultSize);
}
#endregion

#region Properties

/// <summary>
/// The amount of shapes you can fit in a row
/// </summary>
/// <returns></returns>
public int ShapesPerRow
{
get
{
float paddingPlusSize = m_Padding + m_ShapeSize.Width;
// remove some spacing for the margins
float width = m_GraphWidth - (m_Padding * 2);
return Convert.ToInt32(Math.Floor((double)(width / paddingPlusSize)));
}
}

#endregion

#region Public API

/// <summary>
/// Finds the location for the point in the grid
/// </summary>
/// <param name="xy"></param>
/// <returns></returns>
public PointF FindLocation(Point xy)
{
ValidatePoint(xy);
float x = m_Padding;
float y = m_Padding;
x += (xy.X * (m_ShapeSize.Width + m_Padding));
y += (xy.Y * (m_ShapeSize.Height + m_Padding));
return new PointF(x, y);
}

/// <summary>
/// Marks a position in the grid as "occupied"
/// </summary>
/// <param name="xy"></param>
public void MarkAsOccupied(Point xy)
{
ValidatePoint(xy);
if (m_Grid[xy.X, xy.Y] == 1)
{
throw new InvalidOperationException("Point is already occupied");
}
m_Grid[xy.X, xy.Y] = 1;
}

/// <summary>
/// Asks if a particular spot is occupied yet, or not
/// </summary>
/// <param name="xy"></param>
/// <returns></returns>
public bool IsPointOccupied(Point xy)
{
ValidatePoint(xy);
return m_Grid[xy.X, xy.Y] == 1;
}

/// <summary>
/// Asks if a particular spot is occupied yet, or not
/// </summary>
/// <param name="xy"></param>
/// <returns></returns>
public bool IsPointOccupied(int x, int y)
{
return IsPointOccupied(new Point(x, y));
}

#endregion

#region Private Impl

/// <summary>
/// Creates a new grid based on the size and
/// copies the "occpuied" values across.
/// </summary>
/// <param name="size"></param>
private void CalculateNewGrid(int size)
{
int[,] tempGrid = CreateNewGrid(size);
for (int x = 0; x < tempGrid.GetLength(0); x++)
{
for (int y = 0; y < tempGrid.GetLength(1); y++)
{
if (tempGrid[x, y] == 1)
{
if (tempGrid.GetLength(0) >= x
&& tempGrid.GetLength(1) >= y)
{
tempGrid[x, y] = 1;
}
}
}
}
m_Grid = tempGrid;
}

/// <summary>
/// Creates a new grid based on the size and
/// copies the values across.
/// </summary>
/// <param name="size"></param>
/// <returns></returns>
private int[,] CreateNewGrid(int size)
{
int[,] tempGrid = new int[ShapesPerRow, size];

for (int x = 0; x < ShapesPerRow; x++)
{
for (int y = 0; y < size; y++)
{
tempGrid[x, y] = 0;
}
}

return tempGrid;
}

/// <summary>
/// Validates a point, ensures that it not beyond the number
/// of shapes per line and ensures the object has a large enough grid
/// to deal with the request.
/// </summary>
/// <param name="xy"></param>
private void ValidatePoint(PointF xy)
{
if (xy.X ShapesPerRow)
{
throw new ArgumentException("Point's X is too great");
}
// make the grid larger, if necessary
if (xy.Y m_Grid.GetLength(1))
{
CalculateNewGrid((int)Math.Floor(xy.Y));
}
}

#endregion
}
"Heron" <no****@nospam.comwrote in message
news:uW**************@TK2MSFTNGP02.phx.gbl...
Hi,

I'm developing an mapping tool where the shapes are drawn in a canvas with
their related connections, Something like MS SQL server diagramming tool.

Now, I wish to provide an option (like sql server does: "Arrange tables")
to
arrange all shapes so their connections so they can be shown in a
beautifull
way. Can somebody suggest an alogorithm that will organize the shapes in
such a way that the endresult is clean?

Any help is appreciated.

Regards


Mar 13 '07 #2

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Mickel Grönroos | last post by:
Hi, I have a Tkinter.Canvas of variable width. Is there a standard way of asking the canvas which parts of it that is visible? I.e. on the horizontal scale, I would like to know at what fraction...
5
by: Andrew Poulos | last post by:
Is there a right/best way to draw an ellipse using Canvas? (With VML there's the v:oval element which makes the exercise trivial). I tried drawing a 360 degree arc (a circle) and then scaling it...
11
by: Aaron Gray | last post by:
Hi, I have put together a bit of JavaScript to make a square resizable canvas :- http://www.aarongray.org/Test/JavaScript/resizable.html Problems I have :- a) I cannot seem to center it...
3
by: moondaddy | last post by:
I'm working in a WPF windows application and am wondering if it's possible to rotate a Canvas or user control derived from Canvas. I created a user control which derives from Canvas and I need to...
26
by: Jon Davis | last post by:
OK, why is Canvas not IDisposable, and how do I get rid of all the Windows handles? I'm doing a performance test of looping through a dynamic XAML-to-JPEG conversion. It gets to about 500...
2
by: gwoodhouse | last post by:
Hello everyone, IM nearing the end of a peice of work right now - i have everything working bar one tiny line. What i have is 2 Bitmap images that are the same size. What i need is 1 Bitmap...
6
by: Nebulism | last post by:
I have been attempting to utilize a draw command script that loads a canvas, and through certain mouse events, draws rectangles. The original code is from...
1
by: =?Utf-8?B?TWFyaw==?= | last post by:
Hello everyone: I'm trying to teach myself Visual Basic 2005 .NET and the best way I have found is to create a project in Visual Basic 2005 .NET. The project concept is: I want to create a ...
4
by: moondaddy | last post by:
I have a wpf project where I use a canvas to drag shapes around. when I drag a shape beyond the right or bottom side I get scrollbars which is good. I also get scrollbars when I zoom in and a...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.