[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.
Related
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
This seems like a trivial problem, though I've been hitting myself over the head with it for too long.
This doesn't even plot just the (0,0) -- I can't seem to find much about plotting from arrays -- rather just matrix plots (and only columns at that).
The data is properly in these arrays, I just need to make plots! Doesn't seem so complicated. I don't even need separate colors for the different sets...just all one big scatter plot.
Any suggestions?
pdf(mypath)
# Plot first point
plot(0,0, col = "blue", type = "n", xlab="PES", ylab=""%eff")
#Loop to Plot remaining points
for(rows in 1:nrowX)
{
for(cols in 1:ncolX)
{
points(X[rows,cols],Y[rows,cols], col = "blue", type = "p")
}
}
dev.off
I have also tried using plot.new() to have an empty plot...but no such luck.
SOLUTION!!
Turns out I'm just a fool. Code is acurate and the suggestions below do indeed work.
R happened to be open in another tab and since it was open, never let go of the plot (why? I don't know). As soon as it was closed, the plot appeared. Now I can get my plot again and again...
Thanks to everyone who tried helping a problem that wasn't a problem!
I like this place already!
When you set type = "n", the plot function will not plot anything at all. It is used to set up a basis for the rest of the plot (like axis labels, limits etc). That is why the first point at (0, 0) does not show up.
The rest of the points are probably outside the range. Use xlim and ylim to set up the ranges properly. I'm going to assume X and Y have the same size and dimension. Try this:
pdf(mypath)
# Set up the plot
plot(0, type="n", xlab="PES", ylab="%eff", xlim=range(X), ylim=range(y))
# Now plot
points(X,Y, col="blue")
dev.off
Of course you could let the plot function take care of the limits for you:
pdf(mypath)
plot(X, Y, xlab="PES", ylab="%eff")
dev.off()
Your initial plot will set up the coordinates, but since you only give it one point it does not know how much room to leave around the 0,0 point (so it does not leave very much). I expect that the rest of your points fall outside of that range which is why they don't show up on the plot (you can use par("usr") to see what the extents are).
When you create the initial plot you should include xlim and ylim arguments so that the plot includes the area where the new points will be added, something like:
plot(0,0, type='n', xlim=range(X), ylim=range(Y))
You may also be interested in the matplot function which will take a matrix as either or both the x and/or y argument and plot accordingly.
Edit
The following works for me:
X <- matrix( runif(390), nrow=10 )
Y <- matrix( rnorm(390), nrow=10 )
plot(0,0, col = "blue", type = "n", xlab="PES", ylab="%eff",
xlim=range(X), ylim=range(Y))
#Loop to Plot remaining points
for(rows in 1:nrow(X))
{
for(cols in 1:ncol(X))
{
points(X[rows,cols],Y[rows,cols], col = "blue", type = "p")
}
}
I did remove an extra " from the ylab, was that your problem?
But
plot(X,Y)
also worked without the looping.
Check with just the console to see if it works before worrying about sending to a pdf file. If this has not fixed it yet, we still need more details.
I have a code to crop connected components of input image, input, by finding the boundary conditions from a binary image's labelled map, labelledmap ([labelledmap, labelcount] = bwlabel(hvedged, 8);)
I'm new to matlab so this might sound stupid..
The problem is, I am unable to store different cropped images in the same variable, Because matlab seems to merge the ends of the already existing image and the new cropped image, i.e, it is storing the complete map between the two cropped images, the way i see it :/
This is the output Using different variables for storing cropped image (the kind of output i want)
Output Using different variables for storing cropped image
This is the output i'm getting by storing the cropped image in the same variable(not helpful)
Output when storing cropped image in the same varible
I tried using an array of size equal to total number of labels produced but it's giving the same result.. also i tried clearvars for clearing the output token image, ltoken, after every iteration of the loop but it's not helping
So, is there any possible way to display individual cropped images.. also the number of cropped images might be in thousands so i want to use a loop to code their cropping mechanism
here is a part of the code attached.. thanks in advance ;)
for h=1:labelcount
for i=1:r
for j=1:c
if labelledmap(i,j)==h
if i<ltop
ltop=i;
end
if i>lbottom
lbottom=i;
end
if j<lleft
lleft=j;
end
if j>lright
lright=j;
end
end
end
end
if ltop>5
ltop=ltop-5;
end
if lbottom<r-5
lbottom=lbottom+5;
end
if lleft>5
lleft=lleft-5;
end
if lright<c-5
lright=lright+5;
end
lwidth=lright-lleft;
lheight=lbottom-ltop;
ltoken=imcrop(input,[lleft ltop lwidth lheight]);
figure('Name', 'Cropped Token'), imshow(ltoken);
clearvars ltoken;
end
you need to initialize ltop lbottom lleft and lright for each iteration of label h. I think this is the reason why you get the cropped images "glued" together.
It is EXTREMELY inefficient to go through all the pixels for each and every one of your labels. Especially when you are expected to have many labels.
Use regionprops to get the 'BoundingBox' property for each label.
Here's an example
st = regionprops( labelledmap, 'BoundingBox' );
imlist = cell( 1, numel(st) ); % pre-allocate
for ii=1:numel(st)
r = st(ii).BoundingBox;
% I understand you want to increase the BB by 5 pixels at each side:
r(1:2) = r(1:2) - 5; % start point moves -5
r(3:4) = r(3:4) + 10; % width and height increases by 10
imlist{ii} = imcrop( input, r );
end
I'm still a bit in shock by your code that explicitly loops through all pixels just for finding the bouding box. This is NOT the matlab way of doing things.
If you insist on NOT using regionprops here's a more Matlab-ish way of finding the ii-th bounding box:
imsk = (labeledmap == ii); % create a binary map with True for ii-th region
xFlat = any(imsk,1); % "flattening" imsk on the x-axis
lleft = find( xFlat, 1, 'first' );
lright = find( xFlat, 1, 'last' );
yFlat = any(imsk, 2);
ltop = find( yFlat, 1, 'first' );
lbottom = find( yFlat, 1, 'last' );
No loops at all over image coordinates.
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.
I am using Telerik RadChart controls for Silverlight with Silverlight 4.0. I have a problem, due I think to the variance in my data sets, which causes my larger stacked bars to be clipped within the ChartArea. No problem, I thought, I can just loop through all my data and find the maximum size my StackedBar has to be, and adjust the scale of the y-axis. Here's the method I chose to implement.
private void ForceScaleOfYaxis(IEnumerable<ChartObject> chartData)
{
double sum = 0;
foreach (var bar in chartData)
{
sum = Math.Max(sum, bar.Series1 +
bar.Series2 +
bar.Series3 +
bar.Series4 +
bar.Series5);
}
ChartArea chartArea = radChart1.DefaultView.ChartArea;
chartArea.AxisY.AutoRange = true;
double min = chartArea.AxisY.ActualMinValue;
double step = sum / 10;
chartArea.AxisY.AutoRange = false;
chartArea.AxisY.AddRange(min, sum, step);
}
This worked quite well, in that it changed the y-axis to equal the largest sum of series values for the stacked bar.
Now I have a different problem: I correctly set the scale of the y-axis, but the Charts do not appear to stack.
One can see this with the following chart, as seen in this screen shot.
I don't think that this is related to the clipping of bars caused by the YAxis Range but rather the way you Group the data and populate the Chart.
A sample project of yours should shed some more light on the real issue.