Bring graphics to front F# - winforms

I'm doing a project in which you should be able to create shapes in a windows forms environment. I've got two different shapes at the moment, called Circle1 and Rectangle1, they are just what they are called an have similiar properties.
type Rectangle1(x:int, y:int,brush1)=
let mutable thisx = x
let mutable thisy = y
let mutable thiswidth = 50
let mutable thisheight = 20
let mutable brush = brush1
member obj.x with get () = thisx and set x = thisx <- x
member oby.y with get () = thisy and set y = thisy <- y
member obj.brush1 with get () = brush and set brush1 = brush <- brush1
member obj.width with get () = thiswidth and set width = thiswidth <- width
member obj.height with get () = thisheight and set height = thisheight <- height
member obj.draw(g:Graphics) = g.FillRectangle(brush,thisx,thisy,thiswidth,thisheight)
This rectangle is clickable and moveable, but I've encountered a problem. I need some kind of method that is similar to the c# bringToFront() method. So that when I click a shape, my shape goes to the front of all other shapes.
My storage list looks like this:
let mutable RectangleList:List<Rectangle1> = []
And i use a hittest to determine whether the user hit a shape or not:
let rec VilketObjRec (e:MouseEventArgs) (inputlist:List<Rectangle1>) =
match inputlist with
|[] -> None
|head::tail -> if (((e.X >= head.x) && (e.X <= (head.x + head.width))) && (e.Y >= head.y) && (e.Y <= (head.y+head.height)))
then Some(head) else VilketObjRec e tail
Anyone got any kind of idea how to tackle this problem? Cause frankly, I'm lost.

Based on the hit test function, it seems that your RectangleList stores the rectangles in a reversed order than the order in which they appear on the screen (the rectangle at the start is hit tested first and so it will be the one on the top of the drawing).
In that case, if you want to bring a rectangle to the top, you just need to move it to the beginning of the list. You can create a new list with the specified value at the beginning and then remove the value from the rest of the list using filter:
let BringToFront value list =
value :: (List.filter (fun v -> v <> value) list)
The function works on anly list, so here is an example using integers:
BringToFront 3 [ 1;2;3;4 ] = [3;1;2;4]

Wmeyer's and Tomas's answers are nicely meet to your request for relatively small set of rectangles. In case you will use 10^3 and more rectangles and you know their coordinates before your GUI is started, there is simple static structure enter link description here. In more complex case, 3rd chapter of "The Design And Analysis Of Spatial Data Structures" by Hanan Samet is your best friend.

The basic idea: You could add a z coordinate to the Rectangle1 class. When a rectangle is hit, make sure it gets the highest z value. Before drawing the rectangles, make sure they are sorted by ascending z value.

Related

Get every Y value from every line based on a X value

Using OxyPlot library, I have a LineSeries with a max count of 8. Given a X value (got from a left mouse click), how can I get (and show it in the legend) the corresponding Y value for each line?
You can get the point value using the MouseDown method which you attach to your line series found here in the MouseDownEventHitTestResult method
var s1 = new LineSeries();
s1.MouseDown += (s, e) =>
{
model.Subtitle = "Y value of nearest point in LineSeries: " +
Math.Round(e.HitTestResult.NearestHitPoint.Y);
model.InvalidatePlot(false);
};
There doesn't appear to be any way to change much of whats in the legend area as that's just a reflection of the graph titles. You could display it to the subtitle as in the example or draw an annotation on the screen.
They have a whole bunch of examples you can look through for ideas here

MATLAB Add Mouse Click Coordinate to Matrix?

I am creating an image processing project in matlab. I want to get 5 coordinates from image with mouse and save them to a matrix. When I run project, I click only once but the matrix is taking same coordinates. How can I fix it ?
function ImageClickCallback ( objectHandle , eventData )
array = 3:2;
for i = 1:3
axesHandle = get(objectHandle,'Parent');
coordinates = get(axesHandle,'CurrentPoint');
coordinates = coordinates(1,1:2);
array(i,1) = coordinates(1);
array(i,2) = coordinates(2);
end
disp(array);
For example when I click a point on image, I am taking this result. I can't select another points.
99.3806 37.1915
99.3806 37.1915
99.3806 37.1915
A much safer alternative would be to use ginput, with which you can select a variable number of points and store their coordinates easily. You don't need a loop; the coordinates are stored once all the points are selected.
Here is a simple example:
clear
clc
close all
A = imread('peppers.png');
imshow(A,[]);
hold on
%// Number of points
N = 5;
array = zeros(N,2);
%// Use a for loop and plot 1 point at a time.
for k = 1:N
[array(k,1),array(k,2)] = ginput(1);
%// Display the points
scatter(array(k,1),array(k,2),60,'k','filled')
end
Sample output for array:
123.0000 87.0000
95.0000 206.0000
256.0000 85.0000
236.0000 253.0000
395.0000 117.0000
And the image with the points displayed:
Therefore, you could would look like this:
function ImageClickCallback ( objectHandle , eventData )
array = zeros(3,2);
[array(:,1),array(:,2)] = ginput(3);

exchange circle pixels in an image in matlab

All I want is to add a circle into an image of a radius and centre of my choice, however I DO NOT WANT to use plot COMMAND, I want a new output array which has my chosen image and circle on it.
here is my function
function [ out_image ] = draw_circle( in_image,x0,y0,r,value)
where in_image is the input image
x0 y0 he centre of circle and r the radius
value the intensity of image
this is my attempt which does not work
ang=0:pi/100:2*pi
x=r*cos(ang)+x0;
y=r*sin(ang)+y0;
cir=[x,y];
[j,k]=size(cir);
for cir=1:j
for cir=1:k
if cir(i,j)==0
out_image(i,j)=in_image(i,j);
end
end
end
imshow(out_image)
end
I'm pretty sure there are better ways, but following your approach, you might use the following code:
out_image = in_image;
cir = round([r*cos(ang)+x0;r*sin(ang)+y0]);
for i = 1:size(cir,2)
out_image(cir(1,i),cir(2,i),:) = 255;
end
Your for loops did not work the way you wrote them. Also, you should use round to get indices, and not floating point values. However, the circle is quite small (only 1 pixel), which might not be enough for large pictures. See example below. Also, you might need a finer discritization for large pictures, i.e. a larger number of elements in ang.
In case you want a larger linewidth, you can use
lw = 3; % Enter linewidth here
for i = 1:size(cir,2)
out_image(cir(1,i)+(-lw:lw),cir(2,i)+(-lw:lw),:) = 255;
end
EDIT: In case you don't see it. The circle is close to the top left corner.
The complete code for the function is:
function [ out_image ] = draw_circle( in_image,x0,y0,r,value,lw)
out_image = in_image;
ang = 0:pi/100:2*pi;
cir = round([r*cos(ang)+x0;r*sin(ang)+y0]);
for i = 1:size(cir,2)
out_image(cir(1,i)+(-lw:lw),cir(2,i)+(-lw:lw),:) = value;
end
imshow(out_image)
You can call it from command line with
draw_circle(in_image,100,200,50,0,3);
Note, I took the unused value as grayscale value.

Trouble zooming with axis crossing at 0 in Oxyplot

[Edit: I submitted an issue about this on the OxyPlot GitHub]
I have an OxyPlot cartesian graph in a WPF Window with some FunctionSeries. When I set PositionAtZeroCrossing at true for both the axes, several problems appear :
1) The titles are not displayed correctly, one doesn't even appear. Changing the value of TitlePosition does not seem to change anything.
2) When zooming in or moving around, the x axis goes outside the graph area, as shown below :
Both problems do not appear when PositionAtZeroCrossing is not set as true.
I am wondering if there is a correct way to fix those problems, or a workaround (I am not familiar with OxyPlot).
//My PlotModel is binded to the Model of a PlotView in my WPF control.
//FonctionQlimPlim, maxX, maxY, minX and maxY are defined elsewhere
PlotModel plot = new PlotModel()
{
PlotType = PlotType.Cartesian
};
plot.Axes.Add(new LinearAxis()
{
Position = AxisPosition.Bottom,
Minimum = minX,
Maximum = maxX,
Title = "Q (kVAR)",
PositionAtZeroCrossing = true
});
plot.Axes.Add(new LinearAxis()
{
Position = AxisPosition.Left,
Minimum = minY,
Maximum = maxY,
Title = "P (kW)",
PositionAtZeroCrossing = true
});
//One of the FunctionSeries
var f = FonctionQlimPlim;
f.Color = OxyColors.Red;
plot.Series.Add(f);
It seems like the usage for this property is something along the following:
Let's assume your input is an x (horizontal),y (vertical) graph.
Let's say your x values go from 1 to 20, and let's assume that your y values will be a random number between -10 and 10.
So, we're expecting to see a graph with a 20point jumping up and down randomly.
When you set the axis PositionAtZeroCrossing, you're telling Oxyplot to put it where the crossing is at. Here's some screenshots to help you out: Link to bigger image.
So, depending on where your zero is, it might be far far outside of your viewable screen, and hence it seems to not be there.
To be honest, I don't see the point in setting them bot to true, but it might suit some needs I guess.
It was a bug, traced here, that was fixed in October 2014.

Creating sets of similar elements in a 2D array

I am trying to solve a problem that is based on a 2D array. This array contains different kinds of elements (from a total of 3 possible kinds). Lets assume the kind as X, Y, Z.
The array appears to be something like this. Note that it would always be completely filled. The diagram is for illustration.
7 | | | | | | |
6 | | | | | | |
5 | | | | | | |
4 | |X|Z|Y|X| |
3 | |Y|X|Y|Y|X|
2 |Y|Y|X|Z|Z|X|
1 |X|X|Y| |X|X|
0 | | | |Z| | |
0 1 2 3 4 5
I am trying to create sets of elements that are placed adjacent to each other. For example, set1 may comprise of elements of type X located at: (0,1), (1,1), (2,2), (2,3), (1,4). Similarly, set2 may comprise of elements of type Y located at: (3,4), (3,3), 4,3).
Problem: Given any point in the array, it must be capable of adding all elements to the appropriate set and ensuring that there are no two sets that contain the same element. Note that a set is only created if more than 2 adjacent elements of the same kind are encountered.
Moreover, if a certain subset of elements is removed, more elements are added to replace the removed ones. The array must then be re-iterated over to make new sets or modify the existing ones.
Solution: I implemented a recursive solution such that it would iterate over all the adjacent elements of, for example, element X (0,1). Then, while iterating over the 8 possible adjacent elements, it would call itself recursively whenever a type X occurred.
This kind of solution is too much brute-force and inefficient, especially in the case where some elements are replaced with new ones of possibly different types. In such a case, almost the whole array has to be re-iterated to make/modify sets and ensuring that no same element exists in more than one set.
Is there any algorithm to deal efficiently with this kind of problem? I need help with some ideas/suggestions or pseudo codes.
[EDIT 5/8/2013: Fixed time complexity. (O(a(n)) is essentially constant time!)]
In the following, by "connected component" I mean the set of all positions that are reachable from each other by a path that allows only horizontal, vertical or diagonal moves between neighbouring positions having the same kind of element. E.g. your example {(0,1), (1,1), (2,2), (2,3), (1,4)} is a connected component in your example input. Each position belongs to exactly one connected component.
We will build a union/find data structure that will be used to give every position (x, y) a numeric "label" having the property that if and only if any two positions (x, y) and (x', y') belong to the same component then they have the same label. In particular this data structure supports three operations:
set(x, y, i) will set the label for position (x, y) to i.
find(x, y) will return the label assigned to the position (x, y).
union(Z), for some set of labels Z, will combine all labels in Z into a single label k, in the sense that future calls to find(x, y) on any position (x, y) that previously had a label in Z will now return k. (In general k will be one of the labels already in Z, though this is not actually important.) union(Z) also returns the new "master" label, k.
If there are n = width * height positions in total, this can be done in O(n*a(n)) time, where a() is the extremely slow-growing inverse Ackermann function. For all practical input sizes, this is the same as O(n).
Notice that whenever two vertices are adjacent to each other, there are four possible cases:
One is above the other (connected by a vertical edge)
One is to the left of the other (connected by a horizontal edge)
One is above and to the left of the other (connected by a \ diagonal edge)
One is above and to the right of the other (connected by a / diagonal edge)
We can use the following pass to determine labels for each position (x, y):
Set nextLabel to 0.
For each row y in increasing order:
For each column x in increasing order:
Examine the W, NW, N and NE neighbours of (x, y). Let Z be the subset of these 4 neighbours that are of the same kind as (x, y).
If Z is the empty set, then we tentatively suppose that (x, y) starts a brand new component, so call set(x, y, nextLabel) and increment nextLabel.
Otherwise, call find(Z[i]) on each element of Z to find their labels, and call union() on this set of labels to combine them together. Assign the new label (the result of this union() call) to k, and then also call set(x, y, k) to add (x, y) to this component.
After this, calling find(x, y) on any position (x, y) effectively tells you which component it belongs to. If you want to be able to quickly answer queries of the form "Which positions belong to the connected component containing position (x, y)?" then create a hashtable of lists posInComp and make a second pass over the input array, appending each (x, y) to the list posInComp[find(x, y)]. This can all be done in linear time and space. Now to answer a query for some given position (x, y), simply call lab = find(x, y) to find that position's label, and then list the positions in posInComp[lab].
To deal with "too-small" components, just look at the size of posInComp[lab]. If it's 1 or 2, then (x, y) does not belong to any "large-enough" component.
Finally, all this work effectively takes linear time, so it will be lightning fast unless your input array is huge. So it's perfectly reasonable to recompute it from scratch after modifying the input array.
In your situation, I would rely, at least, on two different arrays:
Array1 (sets) -> all the sets and the associated list of points. Main indices: set names.
Array2 (setsDef) -> type of each set ("X", "Y" or "Z"). Main indices: type names.
It might be possible to create more supporting arrays like, for example, one including the minimum/maximum X/Y values for each set to speed up the analysis (although it would be pretty quick anyway, as shown below).
You are not mentioning any programming language, but I include a sample (C#) code because it is the best way to explain the point. Please, don't understand it as a suggestion of the best way to proceed (personally, I don't like Dictionaries/Lists too much; although think that do provide a good graphical way to show an algorithm, even for unexperienced C# users). This code only intends to show a data storage/retrieval approach; the best way to achieve the optimal performance would depend upon the target language and further issues (e.g., dataset size) and is something you have to take care of.
Dictionary<string, List<Point>> sets = new Dictionary<string, List<Point>>(); //All sets and the associated list of points
Dictionary<string, List<string>> setsDef = new Dictionary<string, List<string>>(); //Array indicating the type of information stored in each set (X or Y)
List<Point> temp0 = new List<Point>();
temp0.Add(new Point(0, 0));
temp0.Add(new Point(0, 1));
sets.Add("Set1", temp0);
List<String> tempX = new List<string>();
tempX.Add("Set1");
temp0 = new List<Point>();
temp0.Add(new Point(0, 2));
temp0.Add(new Point(1, 2));
sets.Add("Set2", temp0);
List<String> tempY = new List<string>();
tempY.Add("Set2");
setsDef.Add("X", tempX);
setsDef.Add("Y", tempY);
//-------- TEST
//I have a new Y value which is 2,2
Point targetPoint = new Point(2, 2);
string targetSet = "Y";
//I go through all the Y sets
List<string> targetSets = setsDef[targetSet];
bool alreadyThere = false;
Point candidatePoint;
string foundSet = "";
foreach (string set in targetSets) //Going through all the set names stored in setsDef for targetSet
{
List<Point> curPoints = sets[set];
foreach (Point point in curPoints) //Going through all the points in the given set
{
if (point == targetPoint)
{
//Already-stored point and thus the analysis will be stopped
alreadyThere = true;
break;
}
else if (isSurroundingPoint(point, targetPoint))
{
//A close point was found and thus the set where the targetPoint has to be stored
candidatePoint = point;
foundSet = set;
break;
}
}
if (alreadyThere || foundSet != "")
{
break;
}
}
if (!alreadyThere)
{
if (foundSet != "")
{
//Point added to an existing set
List<Point> curPoints = sets[foundSet];
curPoints.Add(targetPoint);
sets[foundSet] = curPoints;
}
else
{
//A new set has to be created
string newName = "New Set";
temp0 = new List<Point>();
temp0.Add(targetPoint);
sets.Add(newName, temp0);
targetSets.Add(newName);
setsDef[targetSet] = targetSets;
}
}
Where isSurroundingPoint is a function checking whether both points are close one to the other:
private bool isSurroundingPoint(Point point1, Point point2)
{
bool isSurrounding = false;
if (point1.X == point2.X || point1.X == point2.X + 1 || point1.X == point2.X - 1)
{
if (point1.Y == point2.Y || point1.Y == point2.Y + 1 || point1.Y == point2.Y - 1)
{
isSurrounding = true;
}
}
return isSurrounding;
}
You may want to check out region growing algorithms, which are used for image segmentation. These algorithms start from a seed pixel and grow a contiguous region where all the pixels in the region have some property.
In your case adjacent 'pixels' are in the same image segment if they have the same label (ie, kind of element X, Y or Z)
I wrote something to find objects of just one type for another SO question. The example below adds two more types. Any re-iteration would examine the whole list again. The idea is to process the list of points for each type separately. The function solve groups any connected points and removes them from the list before enumerating the next group. areConnected checks the relationship between the points' coordinates since we are only testing points of one type. In this generalized version, the types (a b c) could be anything (strings, numbers, tuples, etc.), as long as they match.
btw - here's a link to a JavaScript example of j_random_hacker's terrific algorithm: http://jsfiddle.net/groovy/fP5kP/
Haskell code:
import Data.List (elemIndices, delete)
example = ["xxyyyz"
,"xyyzzz"
,"yxxzzy"
,"yyxzxy"
,"xyzxyy"
,"xzxxzz"
,"xyzyyz"
,"xyzxyy"]
objects a b c ws = [("X",solve xs []),("Y",solve ys []),("Z",solve zs [])] where
mapIndexes s =
concatMap (\(y,xs)-> map (\x->(y,x)) xs) $ zip [0..] (map (elemIndices s) ws)
[xs,ys,zs] = map mapIndexes [a,b,c]
areConnected (y,x) (y',x') = abs (x-x') < 2 && abs (y-y') < 2
solve [] r = r
solve (x:xs) r =
let r' = solve' xs [x]
in solve (foldr delete xs r') (if null (drop 2 r') then r else r':r)
solve' vs r =
let ys = filter (\y -> any (areConnected y) r) vs
in if null ys then r else solve' (foldr delete vs ys) (ys ++ r)
Sample output:
*Main> objects 'x' 'y' 'z' example
[("X",[[(7,0),(6,0),(5,0),(4,0)]
,[(3,4),(5,2),(5,3),(4,3),(2,2),(3,2),(2,1),(0,1),(1,0),(0,0)]])
,("Y",[[(7,5),(6,4),(7,4),(6,3)],[(4,4),(4,5),(3,5),(2,5)]
,[(4,1),(3,0),(3,1),(0,4),(2,0),(0,3),(1,1),(1,2),(0,2)]])
,("Z",[[(5,5),(6,5),(5,4)]
,[(7,2),(6,2),(5,1),(4,2),(3,3),(1,3),(2,3),(2,4),(1,4),(1,5),(0,5)]])]
(0.02 secs, 1560072 bytes)

Resources