Disable overlapping shapes in Visio C# - c#

I drop shapes onto a Visio page/doc into an area depending on their x, y value. Some of the shapes contain similar x and y coordinates and therefore overlap eachother. Is the there a way to automatically prevent shapes from overlapping on the page? Or can an equation be put in place to move shapes a specific amount of inches to ensure they are no longer overlapping? Below is the code I have implemented so far.
var vApp = new Visio.Application();
Visio.Document vDoc, vStencil;
Visio.Page vPage;
Visio.Shape vToShape, vFromShape, vConnector;
Visio.Master vConnectorMaster, vFlowChartMaster;
double dblXLocation;
double dblYLocation;
Visio.Cell vBeginCell, vEndCell;
int iCount;
string TEMPLATEPATH = #"C:\temp\Test\testtemplate.vsdx";
//Change this constant to match your choice of location and file name.
string SAVENEWFILE = #"C:\temp\test\testfile.vsdx";
//open the template without any open parameters
vDoc = vApp.Documents.Open(TEMPLATEPATH);
vPage = vApp.ActivePage;
//now, load a Stencil containing basic flowchart shapes
vStencil = vApp.Documents.Open(#"C:\temp\test\teststencil.vssx");
vFlowChartMaster = vStencil.Masters[1];
for (iCount = 0; iCount < xValues.Length; iCount++)
{
vFlowChartMaster = vStencil.Masters[aryValues[0, 0]];
dblXLocation = getXLocation(xValues[iCount]);
dblYLocation = getYLocation(yValues[iCount]);
vToShape = vPage.Drop(vFlowChartMaster,
dblXLocation, dblYLocation);
vToShape.Text = names[iCount];
vToShape.TextStyle.ToLower();
vFromShape = vToShape;
vToShape = null;
}
vDoc.Pages[1].Name = "Graph";
try
{
//Delete the previous version of the file.
File.Delete(SAVENEWFILE);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
vDoc.SaveAs(SAVENEWFILE);
vDoc.Close();
vApp.Quit();
vDoc = null;
vApp = null;
GC.Collect();
Attached here are the first 3 shapes that get dropped onto the graph which overlap. There will be approx 70 more shapes to be plotted spread out over the graph with some overlapping.

At least when droping the shapes manually the following 2 flags help avoiding overlaps.
Try them in the code, it may work.
Application.ActiveWindow.Shape.CellsSRC(visSectionObject, visRowMisc, visLOFlags).FormulaU = "1"
Application.ActiveWindow.Shape.CellsSRC(visSectionObject, visRowShapeLayout, visSLOPlowCode).FormulaU = "2"

Related

Setting x,y position of Visio shape to a graph from a template file C#

I have a template file (.vsdx) which contains a graph with a fixed x and y axis that I load into a new Visio document. I've managed to insert a shape onto the Visio document but it doesn't position according to the the x and y axis of the graph.
Example: Setting the vshape with co-ords 0,0 positions to the bottom left corner edge of the document.
I have the following code so far:
//decalre and initialize Visio objects
var vApp = new Visio.Application();
Visio.Document vDoc, vStencil;
Visio.Page vPage;
Visio.Shape vToShape, vFromShape, vConnector;
Visio.Master vConnectorMaster, vFlowChartMaster;
double dblXLocation;
double dblYLocation;
Visio.Cell vBeginCell, vEndCell;
int iCount;
string TEMPLATEPATH = #"C:\temp\TestProject\testTemplate.vsdx";
//Change this constant to match your choice of location and file name.
string SAVENEWFILE = #"C:\temp\TestProject\testFile.vsdx";
vFlowChartMaster = vStencil.Masters[aryValues[0, 0]];
dblXLocation = 1;
dblYLocation = 1;
vToShape = vPage.Drop(vFlowChartMaster,
dblXLocation, dblYLocation);
vToShape.Text = "Test";
vDoc.Pages[1].Name = "Flowchart Example";
try
{
//Delete the previous version of the file.
//Kill(SAVENEWFILE);
File.Delete(SAVENEWFILE);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
vDoc.SaveAs(SAVENEWFILE);
vDoc.Close();
vApp.Quit();
vDoc = null;
vApp = null;
GC.Collect();
The graph that gets loaded onto the Visio doc is here
Ok, thanks for the update comment. In that case, here's a quick sample. I've created a drawing with a basic 'Graph' master shape, which defines an origin, and a 'Dot' master which is simply a small circle to drop as a dta marker.
The code (using LINQPad) looks for the first instance of the Graph master and then looks for 'known' cells (which it's up to you to define) to get hold of the origin. It then drops two 'Dot' shapes relative to the Graph origin.
Here's what the Graph shape looks like:
[Note - that you can reference a PNT type in an X or Y cell and Visio will extract the corresponding X or Y coordinate]
void Main()
{
var vApp = MyExtensions.GetRunningVisio();
var vPag = vApp.ActivePage;
var graphShp = vPag.Shapes.Cast<Visio.Shape>()
.FirstOrDefault(s => s.Master?.Name == "Graph");
if (graphShp != null)
{
var dotMst = vPag.Document.Masters["Dot"];
//Get x / y back as a named tuple
var origin = GetGraphOrigin(graphShp);
//Green fill is the default defined in the master
var greenDotShp = vPag.Drop(dotMst, origin.x, origin.y);
//Use offest based on graph origin
var redDotOffsetX = -0.5;
var redDotOffsetY = 0.25;
var redDotShp = vPag.Drop(dotMst, origin.x + redDotOffsetX, origin.y + redDotOffsetY);
redDotShp.CellsU["FillForegnd"].FormulaU = "RGB(200,40,40)";
}
}
private (double x, double y) GetGraphOrigin(Visio.Shape targetShp)
{
const string originX = "User.OriginOnPageX";
const string originY = "User.OriginOnPageY";
if (targetShp == null)
{
throw new ArgumentNullException();
}
if (targetShp.CellExistsU[originX, (short)Visio.VisExistsFlags.visExistsAnywhere] != 0
&& targetShp.CellExistsU[originY, (short)Visio.VisExistsFlags.visExistsAnywhere] != 0)
{
return (x: targetShp.CellsU[originX].ResultIU,
y: targetShp.CellsU[originY].ResultIU);
}
return default;
}
So if you run this code, you should end up with something like this (assuming you started off with the a drawing as described above):
So there are lots of ways you could approach this, but probably you need some method or reading where in your Graph shape the origin is and then use that in positioning your 'dot' shapes.

Vertical line across multiple line charts with value display for each chart in Winforms

I am trying to create an application which will have four line charts on a single form. When user will drag mouse over these charts, there should be one vertical line crossing each chart and the current value will be shown for each chart. Is there any way how this can be done in C#/.NET and WinForms?
Here is an example of what I am trying to achieve:
I suggest to put your data into one MSChart control with four separate ChartAreas.
For this you need to set their positions because the default layout would be 2x2.
Then you add a VerticalLineAnnotation and make it movable.
In its moving events you trigger the Paint event of the chart, where you calculate the necessary data, i.e. the values to display and positions where to display them.
Here is an example:
The Paint event is coded like this:
private void chart_Paint(object sender, PaintEventArgs e)
{
double xv = VL.X; // get x-value of annotation
for (int i = 0; i < chart.ChartAreas.Count; i++)
{
ChartArea ca = chart.ChartAreas[i];
Series s = chart.Series[i];
int px = (int )ca.AxisX.ValueToPixelPosition(xv);
var dp = s.Points.Where(x => x.XValue >= xv).FirstOrDefault();
if (dp != null)
{
int py = (int )ca.AxisY.ValueToPixelPosition(s.Points[0].YValues[0]) - 20;
e.Graphics.DrawString(dp.YValues[0].ToString("0.00"),
Font, Brushes.Black, px, py);
}
}
}
Note the use of two axis functions to convert between two (of the three) coordinate systems in a chart: We start with data values and go to pixels. The third system is percentages, which we'll meet below when setting up the chartareas..
Also note that for simplicty's sake I assume that there is one Series per ChartArea; so I can use the same index. You could also find the respective Series by seaching for the Series with the right ChartArea.Name field (*).
Feel free to set a different y-position and of course font, formatting etc..
To bring it to live we code these two events:
private void chart_AnnotationPositionChanging(object sender,
AnnotationPositionChangingEventArgs e)
{
chart.Invalidate();
}
private void chart_AnnotationPositionChanged(object sender, EventArgs e)
{
chart.Invalidate();
}
The chart setup including test data creation is a little longer..:
First we declare a class level variable for the annotation. Of course we could also grab it from the chart.Annotations collection..:
VerticalLineAnnotation VL = null;
private void setupbutton_Click(object sender, EventArgs e)
{
chart.ChartAreas.Clear();
chart.Series.Clear();
for (int i = 0; i < 4; i++)
{
ChartArea ca = chart.ChartAreas.Add("CA" + (i+1));
ca.Position = new ElementPosition(0, i*23 + 5, 90, 25);
Series s = chart.Series.Add("S" + (i+1));
s.ChartType = SeriesChartType.Line;
s.MarkerStyle = MarkerStyle.Circle; // make the points stand out
s.MarkerSize = 3;
s.ChartArea = ca.Name; // where each series belongs (*)
for (int j = 0; j < 50; j++) // a few test data
{
s.Points.AddXY(j, Math.Sin((( (j + 1) *(i + 1) ) / 55f) * 10f));
}
}
VL = new VerticalLineAnnotation(); // the annotation
VL.AllowMoving = true; // make it interactive
VL.AnchorDataPoint = chart.Series[0].Points[0]; // start at the 1st point
VL.LineColor = Color.Red;
VL.IsInfinitive = true; // let it go all over the chart
chart.Annotations.Add(VL);
}
If you watch the animation closely you will see the values jump; that is because I only have 50 points. If you wanted to display interpolated values you could do that by finding the other neighbouring point and do some simple math. But in many cases this would be nonsense.
Note that I used some 'magic' numbers when setting the ChartArea.Position. It is in percentages of the Chart and I left a little slack at top and botton and also to the right for the Legend..

How to find whether a PDF file has overlapping text or not, using c#

I have several PDF files, using a Windows application (C#), I need to find out whether the PDF files has overlapping text or not. How can I do it, is there any free third party DLLs to achieve this?
All I have got now is third party DLLs which can get the text/images from a PDF.
My PDFs are full of texts and images. Here, one line of text is printed on top of another line or few texts are printed on top of some images. These kind of overlapping needs to found.
As you can see in the image, those overlapping might have occurred because of bounding boxes overlap and as well as glyphs contours overlap. So these two occurrences in the PDF needs to be found. My PDF doesn't contain any annotations. So overlapping occurs only in the content of pdf. We don't use poor-man's-bold technique for fatter glyph and if that occurs then it shoul be consider as overlapping.
There is not going to be any transparent images in the PDF, only image we might have is the logo or the digital signature at the bottom of the page, any text overlaps this should be considered as overlapping.
PDFs are not created from image(scan). From some text editor it has been created.
The OP clarified in comments:
those overlapping might have occurred because of bounding boxes overlap and as well as glyphs contours overlap. So these two occurrences in the PDF needs to be found.
Whenever the glyph contours themselves overlap, their bounding boxes also overlap.
Thus, it suffices to check for overlapping bounding boxes.
only image we might have is the logo or the digital signature at the bottom of the page, any text overlaps this should be considered as overlapping.
Thus, for text overlapping images we do not need to check whether a blank area in the image is overlapped.
My PDF files doesnt have any annotations.
Thus, we only need to check the page contents (including contents of form xobjects referenced from the page content, allowing recursion).
Furthermore the OP only mentioned text and images. Thus, we can ignore vector graphics.
An approach using iText 7
As I'm more into Java, I first created a prove-of-concept in Java and ported it to .Net later.
Both for Java and .Net the line of action is the same:
We create a event listener for the iText 7 parsing framework which (while processing a page) collects the bounding boxes of text and image elements and eventually can be asked to check whether there are any occurrences of text overlapping text or image.
We parse the content of the page in question using an instance of that event listener class and query it for overlaps. If more pages are to be checked, this can be done over and over again with a new event listener instance for each page.
iText 7 for .Net
The event listener might look like this:
class OverlappingTextSearchingStrategy : IEventListener
{
static List<Vector> UNIT_SQUARE_CORNERS = new List<Vector> { new Vector(0, 0, 1), new Vector(1, 0, 1), new Vector(1, 1, 1), new Vector(0, 1, 1) };
ICollection<Rectangle> imageRectangles = new HashSet<Rectangle>();
ICollection<Rectangle> textRectangles = new HashSet<Rectangle>();
public void EventOccurred(IEventData data, EventType type)
{
if (data is ImageRenderInfo) {
ImageRenderInfo imageData = (ImageRenderInfo)data;
Matrix ctm = imageData.GetImageCtm();
List<Rectangle> cornerRectangles = new List<Rectangle>(UNIT_SQUARE_CORNERS.Count);
foreach (Vector unitCorner in UNIT_SQUARE_CORNERS)
{
Vector corner = unitCorner.Cross(ctm);
cornerRectangles.Add(new Rectangle(corner.Get(Vector.I1), corner.Get(Vector.I2), 0, 0));
}
Rectangle boundingBox = Rectangle.GetCommonRectangle(cornerRectangles.ToArray());
Console.WriteLine("Adding image bounding rectangle {0}.", boundingBox);
imageRectangles.Add(boundingBox);
} else if (data is TextRenderInfo) {
TextRenderInfo textData = (TextRenderInfo)data;
Rectangle ascentRectangle = textData.GetAscentLine().GetBoundingRectangle();
Rectangle descentRectangle = textData.GetDescentLine().GetBoundingRectangle();
Rectangle boundingBox = Rectangle.GetCommonRectangle(ascentRectangle, descentRectangle);
if (boundingBox.GetHeight() == 0 || boundingBox.GetWidth() == 0)
Console.WriteLine("Ignoring empty text bounding rectangle {0} for \"{1}\".", boundingBox, textData.GetText());
else
{
Console.WriteLine("Adding text bounding rectangle {0} for \"{1}\" with 0.5 margins.", boundingBox, textData.GetText());
textRectangles.Add(boundingBox.ApplyMargins<Rectangle>(0.5f, 0.5f, 0.5f, 0.5f, false));
}
} else if (data is PathRenderInfo) {
// TODO
} else if (data != null)
{
Console.WriteLine("Ignored {0} event, class {1}.", type, data.GetType().Name);
}
else
{
Console.WriteLine("Ignored {0} event with null data.", type);
}
}
public ICollection<EventType> GetSupportedEvents()
{
// Support all events
return null;
}
public bool foundOverlappingText()
{
bool result = false;
List<Rectangle> textRectangleList = new List<Rectangle>(textRectangles);
while (textRectangleList.Count > 0)
{
Rectangle testRectangle = textRectangleList[textRectangleList.Count - 1];
textRectangleList.RemoveAt(textRectangleList.Count - 1);
foreach (Rectangle rectangle in textRectangleList)
{
if (intersect(testRectangle, rectangle))
{
Console.WriteLine("Found text intersecting text with bounding boxes {0} at {1},{2} and {3} at {4},{5}.",
testRectangle, testRectangle.GetX(), testRectangle.GetY(), rectangle, rectangle.GetX(), rectangle.GetY());
result = true;// if only the fact counts, do instead: return true
}
}
foreach (Rectangle rectangle in imageRectangles)
{
if (intersect(testRectangle, rectangle))
{
Console.WriteLine("Found text intersecting image with bounding boxes {0} at {1},{2} and {3} at {4},{5}.",
testRectangle, testRectangle.GetX(), testRectangle.GetY(), rectangle, rectangle.GetX(), rectangle.GetY());
result = true;// if only the fact counts, do instead: return true
}
}
}
return result;
}
bool intersect(Rectangle a, Rectangle b)
{
return intersect(a.GetLeft(), a.GetRight(), b.GetLeft(), b.GetRight()) &&
intersect(a.GetBottom(), a.GetTop(), b.GetBottom(), b.GetTop());
}
bool intersect(float start1, float end1, float start2, float end2)
{
if (start1 < start2)
return start2 <= end1;
else
return start1 <= end2;
}
}
This event listener can be used like this:
PdfReader reader = new PdfReader(pdf);
PdfDocument document = new PdfDocument(reader);
PdfDocumentContentParser contentParser = new PdfDocumentContentParser(document);
OverlappingTextSearchingStrategy strategy = contentParser.ProcessContent(page, new OverlappingTextSearchingStrategy());
bool foundOverlaps = strategy.foundOverlappingText();
iText 7 for Java
The event listener might look like this:
public class OverlappingTextSearchingStrategy implements IEventListener {
static List<Vector> UNIT_SQUARE_CORNERS = Arrays.asList(new Vector(0,0,1), new Vector(1,0,1), new Vector(1,1,1), new Vector(0,1,1));
Set<Rectangle> imageRectangles = new HashSet<>();
Set<Rectangle> textRectangles = new HashSet<>();
#Override
public void eventOccurred(IEventData data, EventType type) {
if (data instanceof ImageRenderInfo) {
ImageRenderInfo imageData = (ImageRenderInfo) data;
Matrix ctm = imageData.getImageCtm();
List<Rectangle> cornerRectangles = new ArrayList<>(UNIT_SQUARE_CORNERS.size());
for (Vector unitCorner : UNIT_SQUARE_CORNERS) {
Vector corner = unitCorner.cross(ctm);
cornerRectangles.add(new Rectangle(corner.get(Vector.I1), corner.get(Vector.I2), 0, 0));
}
Rectangle boundingBox = Rectangle.getCommonRectangle(cornerRectangles.toArray(new Rectangle[cornerRectangles.size()]));
logger.info(String.format("Adding image bounding rectangle %s.", boundingBox));
imageRectangles.add(boundingBox);
} else if (data instanceof TextRenderInfo) {
TextRenderInfo textData = (TextRenderInfo) data;
Rectangle ascentRectangle = textData.getAscentLine().getBoundingRectangle();
Rectangle descentRectangle = textData.getDescentLine().getBoundingRectangle();
Rectangle boundingBox = Rectangle.getCommonRectangle(ascentRectangle, descentRectangle);
if (boundingBox.getHeight() == 0 || boundingBox.getWidth() == 0)
logger.info(String.format("Ignoring empty text bounding rectangle %s for '%s'.", boundingBox, textData.getText()));
else {
logger.info(String.format("Adding text bounding rectangle %s for '%s' with 0.5 margins.", boundingBox, textData.getText()));
textRectangles.add(boundingBox.applyMargins(0.5f, 0.5f, 0.5f, 0.5f, false));
}
} else if (data instanceof PathRenderInfo) {
// TODO: vector graphics
} else if (data != null) {
logger.fine(String.format("Ignored %s event, class %s.", type, data.getClass().getSimpleName()));
} else {
logger.fine(String.format("Ignored %s event with null data.", type));
}
}
#Override
public Set<EventType> getSupportedEvents() {
// Support all events
return null;
}
public boolean foundOverlappingText() {
boolean result = false;
List<Rectangle> textRectangleList = new ArrayList<>(textRectangles);
while (!textRectangleList.isEmpty())
{
Rectangle testRectangle = textRectangleList.remove(textRectangleList.size() - 1);
for (Rectangle rectangle : textRectangleList) {
if (intersect(testRectangle, rectangle)) {
logger.info(String.format("Found text intersecting text with bounding boxes %s at %s,%s and %s at %s,%s.",
testRectangle, testRectangle.getX(), testRectangle.getY(), rectangle, rectangle.getX(), rectangle.getY()));
result = true;// if only the fact counts, do instead: return true
}
}
for (Rectangle rectangle : imageRectangles) {
if (intersect(testRectangle, rectangle)) {
logger.info(String.format("Found text intersecting image with bounding boxes %s at %s,%s and %s at %s,%s.",
testRectangle, testRectangle.getX(), testRectangle.getY(), rectangle, rectangle.getX(), rectangle.getY()));
result = true;// if only the fact counts, do instead: return true
}
}
}
return result;
}
boolean intersect(Rectangle a, Rectangle b) {
return intersect(a.getLeft(), a.getRight(), b.getLeft(), b.getRight()) &&
intersect(a.getBottom(), a.getTop(), b.getBottom(), b.getTop());
}
boolean intersect(float start1, float end1, float start2, float end2) {
if (start1 < start2)
return start2 <= end1;
else
return start1 <= end2;
}
Logger logger = Logger.getLogger(OverlappingTextSearchingStrategy.class.getName());
}
This event listener can be used like this:
PdfReader reader = new PdfReader(pdf);
PdfDocument document = new PdfDocument(reader);
PdfDocumentContentParser contentParser = new PdfDocumentContentParser(document);
OverlappingTextSearchingStrategy strategy = contentParser.processContent(pageNumber, new OverlappingTextSearchingStrategy());
boolean foundOverlaps = strategy.foundOverlappingText();
Remarks
As you can see I don't store the text bounding boxes as they are but instead
boundingBox.applyMargins(0.5f, 0.5f, 0.5f, 0.5f, false),
i.e. slightly smaller boxes. This is done to prevent false positives which otherwise might occur for tightly set text or text with kerning applied. You may have to fine tune the margin values here.
It may be as easy as the example above or you have to implement your own reader for this.
If you have not the full control over your PDF files, you have no chance to solve your problem. The defined boxes can be transformed later on. So you have to parse the whole file, too keep track of the box position and form. Additionally some boxes may be on top of other boxes, but render without any collision on the pixel level.
Than you will run into the next problem. Each PDF implementation has different errors. So your system may render the text perfectly but not the printer of your customer.
Welcome to hell ;)
Each support guy will tell you that they obey the standard. The others must have implemented their PDF library faulty. Because your customers data will be confident, you cannot proof them wrong. You may find some errors with your test data, but never ever the same errors of your customer documents.
Run and hide as long as you have not become the PDF expert of your company.
Here is a dirty "general" method: render your text without the text in bitmap. render the page with your text in another bitmap, compare the area with your text. But this will need a monochrome background. But the load will be really high. But this document looks like a form. Create a form and fill out the form boxes. So you will have no problems and you will even get correct results, fills the form with another program
Hello I have a code sample that uses not free library, but I think other libraries should have similar functionality, so you may use it as the idea:
Before use the following code sample please ensure that you use the latest version of the Apitron PDF Kit.
using System;
using System.Collections.Generic;
using System.IO;
using Apitron.PDF.Kit.FixedLayout;
using Apitron.PDF.Kit.FixedLayout.Content;
using Apitron.PDF.Kit.FixedLayout.PageProperties;
using FixedLayout.Resources;
using FixedLayout.ContentElements;
/// <summary>
/// Gets all text boundaries.
/// </summary>
/// <param name="elements">The elements.</param>
/// <param name="boundaries">The boundaries.</param>
public void GetAllTextBoundaries(IContentElementsEnumerator elements, IList<Boundary> boundaries, Boundary offset)
{
// We dont count drawings and images here - only text;
if(elements == null)
{
return;
}
foreach (IContentElement element in elements)
{
TextContentElement text = element as TextContentElement;
if (text != null)
{
foreach (TextSegment segment in text.Segments)
{
Boundary currentBoundary = segment.Boundary;
if (offset != null)
{
currentBoundary = new Boundary(currentBoundary.Left + offset.Left, currentBoundary.Bottom + offset.Bottom, currentBoundary.Right + offset.Left, currentBoundary.Top + offset.Bottom);
}
boundaries.Add(currentBoundary);
}
}
else if (element is FormContentElement)
{
Boundary currentBoundary = (element as FormContentElement).Boundary;
if (offset != null)
{
currentBoundary = new Boundary(currentBoundary.Left + offset.Left, currentBoundary.Bottom + offset.Bottom, currentBoundary.Right + offset.Left, currentBoundary.Top + offset.Bottom);
}
this.GetAllTextBoundaries((element as FormContentElement).FormXObject.Elements, boundaries, currentBoundary);
}
}
}
/// <summary>
/// Checks if text is overlapped.
/// </summary>
/// <returns></returns>
public bool CheckIfTextIsOverlapped(string fileName)
{
const double overlapMax = 5;
using (System.IO.Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite))
{
using (FixedDocument document = new FixedDocument(stream))
{
foreach (Page page in document.Pages)
{
IList<Boundary> boundaries = new List<Boundary>();
foreach (Annotation annotation in page.Annotations)
{
// Actually we need only Normal state, but will check all - to be sure.
if(annotation.Appearance.Normal != null)
{
this.GetAllTextBoundaries(annotation.Appearance.Normal.Elements, boundaries, annotation.Boundary);
}
}
IContentElementsEnumerator elements = page.Elements;
this.GetAllTextBoundaries(elements, boundaries, null);
for (int i = 0; i < boundaries.Count; i++)
{
for (int j = i + 1; j < boundaries.Count; j++)
{
Boundary b1 = boundaries[i];
Boundary b2 = boundaries[j];
double x1 = Math.Max(b1.Left, b2.Left);
double y1 = Math.Max(b1.Bottom, b2.Bottom);
double x2 = Math.Min(b1.Right, b2.Right);
double y2 = Math.Min(b1.Top, b2.Top);
// So we have intersection
if (x1 < x2 && y1 < y2)
{
if (x1 - x2 >= overlapMax || y1 - y2 >= overlapMax)
{
return true;
}
}
}
}
}
}
}
return false;
}

Displaying pictureBox array

I would like to display 13 pictureBox, however, it ends up with only the last one visible.
So I was wondering if I did it in a wrong way.
The following code get image from resources folder.
var testP = new PictureBox();
for (int i = 0; i < 13; i++)
{
testP.Width = 65;
testP.Height = 80;
testP.BorderStyle = BorderStyle.None;
testP.SizeMode = PictureBoxSizeMode.StretchImage;
test[i] = getImage(testP, testPTemp[i]);
}
The following code is trying to display 13 pictureBox with shifting location.
These two codes segments should be able to perform the action.
test = new PictureBox[13];
for (var i = 0; i < 13; i++)
{
test[i].Image = (Image)Properties.Resources.ResourceManager.GetObject("_" + testTemp[i]);
test[i].Left = 330;
test[i].Top = 500;
test[i].Location = new Point(test[i].Location.X + 0 * displayShift, test[i].Location.Y);
this.Controls.Add(test[i]);
}
Here is the getImage()
private PictureBox getImage(PictureBox pB, string i) // Get image based on the for loop number (i)
{
pB.Image = (Image)Properties.Resources.ResourceManager.GetObject("_" + i); // Get the embedded image
pB.SizeMode = PictureBoxSizeMode.StretchImage;
return pB;
}
I'm pretty sure there are all PictureBox Controls but they have all the same location so they are lying above each other. That's why only the last one is visible to you.
I think you should replace the 0 with the i variable.
test[i].Location = new Point(test[i].Location.X + i * displayShift, test[i].Location.Y); this.Controls.Add(test[i]);
It's hard to tell the exact problem based off the code you've provided. One possible issue could be that when you are creating the PictureBoxes you only create a single instance before the for loop and then fill the array with references to that instance. Another possibility is that when you're calculating the X position of the controls, you're multiplying by 0 which will always result in 0 (meaning all the controls are at location 330).
Below is code that will achieve basically what you're trying but without all your code I can't give you a more specific example.
In Your Class
const int PICTURE_WIDTH = 65;
const int PICTURE_HEIGHT = 85;
Inside You Function
//Loop through each image
for(int i = 0; i < testTemp[i].length; i++)
{
//Create a picture box
PictureBox pictureBox = new PictureBox();
pictureBox.BorderStyle = BorderStyle.None;
pictureBox.SizeMode = PictureBoxSizeMode.StretchImage;
//Load the image date
pictureBox.Image = (Image)Properties.Resources.ResourceManager.GetObject("_" + testTemp[i]);
//Set it's size
pictureBox.Size = new Size(PICTURE_WIDTH, PICTURE_HEIGHT);
//Position the picture at (330,500) with a left offset of how many images we've gone through so far
pictureBox.Location = new Point(330 + (i * PICTURE_WIDTH), 500);
//Add the picture box to the list of controls
this.Controls.Add(pictureBox);
}
If you need to keep a list of the picture boxes, just create a new list before the loop and add each pictureBox to the list inside the loop. If the control/window you're adding these PictureBoxes to needs to scroll left or right to see all the images set the AutoScroll property to true.

Looking for example for plotting Volumetric Slice in Ilnumerics

is there any example for plotting volumetric slice in Ilnumerics use community version. This is an example I got from matlab website:
Volumetric slice image example of matlab
I have array X, Y, Z as posistions and V (velocity) as value for color plotting. All I have done is use Ilpoints to plot that V in position X, Y, Z not , a surfaces. Here are My Code and the result,
ILArray<float> plotXY = ILMath.zeros<float>(3, XcoordinateXY.Length);
plotXY["0;:"] = ILMath.tosingle(SurfaceXY[":;:;1"]);
plotXY["1;:"] = ILMath.tosingle(SurfaceXY[":;:;2"]);
plotXY["2;:"] = ILMath.tosingle(SurfaceXY[":;:;3"]);
ILArray<float> ColorMap = ILMath.tosingle(SurfaceXY[":;:;0"]);
var ilsurfaceplotXY = new ILPoints()
{
/*Wireframe = { Color = Color.FromArgb(50, Color.LightGray) },
Colormap = new ILColormap(dataXY),
Children = { new ILColorbar() }*/
Positions = plotXY,
Colors = cm.Map(ColorMap).T,
Color = null
};
Here are code for displaying:
var scene = new ILScene();
scene.Add(
new ILPlotCube
{
TwoDMode = false,
Axes =
{
XAxis =
{
Label = { Text = "UTM X (Km)" },
GridMajor =
{
DashStyle = DashStyle.Dashed,
Color = Color.DarkGray,
Width = 1
}
},
YAxis =
{
Label = { Text = "UTM Y (Km)" },
GridMajor =
{
DashStyle = DashStyle.Dashed,
Color = Color.DarkGray,
Width = 1
}
},
ZAxis =
{
Label = { Text = "DEPTH (Km)" },
GridMajor =
{
DashStyle = DashStyle.Dashed,
Color = Color.DarkGray,
Width = 1
}
}
},
Children = { ilsurfaceplotXY, ilsurfaceplotXZ, ilsurfaceplotYZ },
}
);
this.ilPanel1.Scene = scene;
this.ilPanel1.Scene.Configure();
this.ilPanel1.Refresh();
And here is an image result.
Result Image
I'm sorry the image is in the link.
Regarding the visualization this can be done with regular surfaces, imagesc plots, or the new fast surface in the Drawing2 toolbox. They all allow to provide X,Y, and Z values as well as a color for each grid point or tile.
Regarding the computation of the points: it seems that you just pick points from the available set. It would be much better to interpolate between these points. The Interpolation Toolbox provides functions for the interpolation of gridded and scattered data. (In your case the data seem to be gridded ?). This allows to have slices in arbitrary orientation / angles. The interpolation toolbox interpolates the positions of the slice grid points as well as the values for the colors.
From an online example:
The setup of the horizontal slices is done as follows:
ILArray<float> C;
for (int i = 0; i < m_nrSlices; i += m_nrSlices / 4) {
C = m_V[":",":", i];
pc1.Add(new ILSurface(grid + i, C, colormap: Colormaps.Bone)
{
Wireframe = { Visible = false },
});
}
Here, m_V is your 3D dataset, handled as 3D array. pc is the plot cube. The surfaces are simply added to the plot cube. The points of the red interpolated area are dynamically computed as the user moves the red balls:
// Points on the cutting area are considered scattered points, because the area is not (necessarily) plain. However, V
// is a grid. interp3s interpolates the scattered points very efficiently.
// Note how the shape of the coordinate arrays Xn, Yn and Zn is not important. interp3s takes their elements in sequential order.
// The output is a vector of interpolated values. (We gonna reshape it below.)
ILArray < float> Z = Interpolation.interp3s(m_V, m_x, m_x, m_x, m_Xn, m_Yn, Zn, method: InterpolationMethod.cubic);
// let's plot! We get a reference to the fast surface
var fsurf = ilPanel1.Scene.First<ILFastSurface>("dynslice");
if (fsurf != null) {
// first time setup only: provide the full coordinates of X and V. Here it is sufficient to provide grid vectors.
if (fsurf.Cols == 0) {
fsurf.Update(X: m_xn * res, Y: m_xn * res, Z: Zn * res, C: ILMath.reshape(Z, Zn.S), colormap: Colormaps.Hot);
} else {
// the grid was configured already and did not change. we save some recomputing by ommiting the X and Y coordinates, prevent from reshaping buffers.
fsurf.Update(Z: Zn * res, C: ILMath.reshape(Z, Zn.S), colormap: Colormaps.Hot);
}
}
fsurf.Configure();
ilPanel1.Refresh();
To go into the details is out of scope for SO. You can download the example and run it on your machine. You will need a recent version of ILNumerics though.
EDIT: Axis aligned slices as in the plot you provided are only a subdomain, of course. Generating them works in the very same way:

Categories

Resources