JFreeChart: crosshair label custom position - jfreechart

Is it possible to place crosshair label in the custom position? I have x and y crosshair. I want that y crosshair label was positioned near the data point (change label offset X coordinate).
The problem is that RectangleAnchor has no such option
Crosshair yCrosshair = new Crosshair(Double.NaN, Color.DARK_GRAY, new BasicStroke(0f));
yCrosshair.setLabelAnchor(RectangleAnchor.CENTER);
And it seems that JFreeChart completely ignores label offset settings:
Crosshair yCrosshair = new Crosshair(Double.NaN, Color.DARK_GRAY, new BasicStroke(0f));
yCrosshair.setLabelXOffset(5);
I have the desired plot coordinates for the label in the mouse listener but I can't find how to apply it to the label position.

Ok I've solved my problem by using XYPointerAnnotation.
XYPointerAnnotation pointer = new XYPointerAnnotation( "", 0, 0, 7.0 * Math.PI / 4.0 );
pointer.setTipRadius(3.0);
pointer.setBaseRadius(15.0);
pointer.setPaint(Color.blue);
pointer.setTextAnchor(TextAnchor.HALF_ASCENT_LEFT);
pointer.setBackgroundPaint(new Color(180, 180, 180, 180));
And on mouse move event I've position the annotation to the desired point
mainPlot.removeAnnotation(pointer);
if ( !sY.isNaN() ) {
pointer.setX(x);
pointer.setY(sY);
pointer.setText("POWER: "+ sY);
mainPlot.addAnnotation(pointer);
}

Related

Add border to cartesianchart LiveCharts

I want to add a border to a cartesianchart in LiveCharts for a c# winforms project
I've tried some extensive searching and examples on github but no hints.
There is a BorderBrush & BorderThickness in Base, but don't know how to set:
cartesianchart1.Base.BorderBrush
Current workaround is using the code below to draw a line and the min and max of both X & Y axis.
Sections = new SectionsCollection
{
new AxisSection
{
Value = 0.25,
StrokeThickness = 1,
Stroke = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(0, 0, 0))
},
}

Wpf text rotation

I want to add some text on a canvas and decided to use textBlock for that (to set Font etc.)
But I cannot figure out how to rotate it.
I use the following function to add myText on myCanvas:
void text(double x_pos, double y_pos, string myText, double angle, Point rot_cen, Color color1)
{
TextBlock textBlock = new TextBlock()
{
Text = myText,
FontFamily = new FontFamily("Verdana"),
FontSize = 16,
TextAlignment = TextAlignment.Center
};
textBlock.Foreground = new SolidColorBrush(color1);
Canvas.SetLeft(textBlock, x_pos);
Canvas.SetTop(textBlock, y_pos);
textBlock.RenderTransform = new RotateTransform(angle, rot_cen.X, rot_cen.Y);
myCanvas.Children.Add(textBlock);
}
From what I've read rot_cen is a point from (0,0) - which is top left corner to (1,1) - which is bottom right corner. But when i set it to be (0.5,0.5) it still rotates around top left corner. Do I need to update it somehow?
The CenterX and CenterY properties of a RotateTransform use absolute coordinates.
You may want to set RenderTransformOrigin, which uses relative coordinates:
textBlock.RenderTransformOrigin = rot_cen;
textBlock.RenderTransform = new RotateTransform(angle);

Reduce space between legend and chart in jfree Pie chart

I placed the legend in the top left corner and there is an unnecessary gap between the chart and the legend.
How to reduce this?
There is considerable amount of space between pie chart and its border.
public void setPie() {
RingPlot plot = (RingPlot) this.chart.getPlot();
plot.setSectionPaint("", WHITE_COLOR);
plot.setCircular(true);
plot.setShadowPaint(null);
}
public void setLegend() {
LegendTitle legend = this.chart.getLegend();
legend.setVerticalAlignment(VerticalAlignment.TOP);
legend.setVisible(true);
legend.setPosition(RectangleEdge.LEFT);
Rectangle rect = new Rectangle(LEGEND_LENGTH, LEGEND_WIDTH);
RingPlot plot = (RingPlot) this.chart.getPlot();
plot.setLegendItemShape((Shape) rect);
}
You could try tweaking the margins around the LegendTitle. Something like:
chart.getLegend().setMargin(top, left, bottom, right);
EDIT: As suggested in the post in the comments, you could try to draw the legend manually at a given position:
//Print legend at X & Y location
Rectangle2D r2DD = new Rectangle2D.Double(119, 47, 120, 180);
LegendTitle legend = new LegendTitle(chart.getPlot());
legendTitle.draw(g2,r2DD);
But I'm not sure how to implement it, as you need access to the ChartPanel's Graphics2D. Perhaps by extending ChartPanel and overriding paintComponent(Graphics g) ?

WPF - How to work out how much of a canvas background image is cropped?

I have a canvas with a background image:
var bi = new BitmapImage(new Uri(imgLocFull));
var ib = new ImageBrush(bi) {Stretch = Stretch.UniformToFill};
MyCanvas.Background = ib;
I am overlaying various shapes on the image, and want the position of the shapes relative to the background image to be fixed.
If my application window is resized, the amount of the image that is cropped, horizontally and vertically, changes, and when my shapes are redrawn, they do not appear in the same position on the background image.
How can I determine how much of the image has been cropped (to apply an adjustment factor to the overlaid objects' positions?) Or is there a better way of fixing the location of a shape relative to the background image?
Here is my present drawing code:
var l = new Ellipse();
var scb = new SolidColorBrush();
scb.Color = Color.FromRgb(rCol, gCol, bCol);
l.Fill = scb;
l.StrokeThickness = 0;
l.Width = 3;
l.Height = 3;
Canvas.SetBottom(l, point.Y); // * clipping factor here?
Canvas.SetLeft(l, point.X); // * clipping factor here?
MyCanvas.Children.Add(l);
EDIT: Further Clarification
Here's a concrete example of what I am trying to achieve. My image is an aerial photograph, and I want to mark a particular geographical feature (with, say, an ellipse.)
When the window is resized, the ellipse doesn't stay on the feature, it stays relative to the left and top of the canvas.
I can get it closer to the right place by moving it using a factor (newx = newheight/oldheight * oldx) but this doesn't quite work because of the UniformToFill stretch mode, which sees some of the image clipped off the canvas.
The Top and Left of the Canvas are 'anchored', while the Bottom and Right move when resizing... try setting the Canvas.Top Attached Property instead, along with the Canvas.Left Attached Property as you are:
var l = new Ellipse();
var scb = new SolidColorBrush();
scb.Color = Color.FromRgb(rCol, gCol, bCol);
l.Fill = scb;
l.StrokeThickness = 0;
l.Width = 3;
l.Height = 3;
Canvas.SetTop(l, point.Y); // * clipping factor here?
Canvas.SetLeft(l, point.X); // * clipping factor here?
MyCanvas.Children.Add(l);
UPDATE >>>
You asked Or is there a better way of fixing the location of a shape relative to the background image?
I answered this question, so I don't understand why you would need to do anything else... your objects will not move when the screen in resized *if you only set the Grid.Top and Grid.Left properties.

Piemenu for WPF

Are there any working piemenu controls for WPF?
I've found this in my favorite , you can take a look at :
This
have a nice day.
This question is probably long dead, but just a note that the control Thomas M posted, while awesome, has a major issue: You need to mouse over and click on the actual item instead of the pie slice. This means that the pie slices are not completely adjacent and IMO defeats a lot of the clickability (Frits's law) advantages of the control. So while it looks like a pie menu, it really just positions everything radially.
I ended up doing this:
private static Path makeDeliciousKeyLimePieSlice(double innerRadius, double outerRadius,
double startAngle, double endAngle, Vector ofs)
{
Point p1 = new Point(Math.Cos(endAngle) * innerRadius, Math.Sin(endAngle) * innerRadius) + ofs;
Point p2 = new Point(Math.Cos(startAngle) * innerRadius, Math.Sin(startAngle) * innerRadius) + ofs;
Point p3 = new Point(Math.Cos(startAngle) * outerRadius, Math.Sin(startAngle) * outerRadius) + ofs;
Point p4 = new Point(Math.Cos(endAngle) * outerRadius, Math.Sin(endAngle) * outerRadius) + ofs;
PathFigure fig = new PathFigure(p1, new PathSegment[] {
new ArcSegment(p2, new Size(innerRadius, innerRadius), endAngle - startAngle, false, SweepDirection.Counterclockwise, true),
new LineSegment(p3, true),
new ArcSegment(p4, new Size(outerRadius, outerRadius), startAngle - endAngle, false, SweepDirection.Clockwise, true),
}, true).GetAsFrozen();
return new Path { Data = new PathGeometry(new[] { fig }).GetAsFrozen() };
}
This will create a "slice" of the pie. You can style this how you want if you want a true pie menu. Another option is to make it transparent (set the fill to Brushes.Transparent; it must have a fill to be hit-test visible), which looks good for radial context menus. Here's my WIP after about half an hour's work (I know the spacing sucks):
alt text http://public.blu.livefilestore.com/y1pdW5ibqWquKGosMSch9C5KmOTKkiZ35mAI7iFKKUKf3cm7TGSquXhO8hkkL9Ln6Z3tKn74u67C27Qb_AIWQxzhg/radial.png?psid=1
EDIT: ah; the cursor doesn't appear in the shot -- basically, if you use the path overlay, you can have the mouse outside the actual control but still have it highlighted.
This control needs a bit of work still but it's a great starting point and supports multiple levels of items. (ie: a hierarchy) Check it out here

Resources