I need to make circle with bar.
Here is my image when someone will still not understand:
Does any existing control work? Or should I create a new control somehow? I used a new control with circle filled with gradient but it isn't the same effect :(
I also tried to draw a circle but when I do in my math cycle with sin and cos it does something what I do not want.
double slice = 2 * Math.PI / 360;
for (int i = 0; i < 360; i++)
{
double angle = slice * i;
int x = (int)(0 + 300 * Math.Cos(angle)); // start x + radius * ...
int y = (int)(0 + 300 * Math.Sin(angle));
Line line = new Line()
{
X1 = 0,
Y1 = 0,
X2 = x,
Y2 = y,
Stroke = new SolidColorBrush(Colors.Red),
StrokeThickness = 1.0
};
canvas.Children.Add(line);
}
EDIT: Metro = Xaml!!!
Related
I have a circle, with a specific radius. Inside the circle I have a point with the X, Y coords. I also have a heading, for example 210. How can I get a random point INSIDE THE CIRCLE on the segment that I draw from the point to the margin of the circle? Thanks!
double radiusCircle = 10;
double y = -3;
double x = -Math.Sqrt(3 * 9);
double angleRad = Math.Atan2(y, x);
double angleDeg = angleRad * 180 / Math.PI; // 210 (-150) degrees
double distancePointCenter = Math.Sqrt(x * x + y * y);
double distancePointMargin = radiusCircle - distancePointCenter;
Random rand = new Random(123);
for (int i = 0 i < 10; i++)
{ // Generate 10 random points
double randomPointDistToCenter = distancePointCenter + distancePointMargin * rand.NextDouble();
double xRandomPoint = randomPointDistToCenter * Math.Cos(angleRad);
double yRandomPoint = randomPointDistToCenter * Math.Sin(angleRad);
}
I have two fits images from the WFC3 that I am trying to combine with a C# program. When I try to combine multiple images I don't think the values I am getting for my x/y coordinates (calculated from Right Ascension/Declination) are correct. I am expecting a final image that is about the same width as the two images combined, but it turns out to be about the same width and about twice the height. I know the final image should be about double the width of a single image because I manually combined the images in photoshop and the final image was about twice as wide as either of the two original images.
NOTE: when I say "image" they are fits images, so they are just a bunch of single values in a file, so to combine them I create a new file and initialize the correct number of single values (width * height) to zero, and then fill in the values from the images I am using to combine. They are not jpg or tif or png.
I am using the following formula to change from world coordinate system to cartesian:
formula is (since distance is the same for everything):
x = cos(dec) * cos(ra)
y = cos(dec) * sin(ra)
I get the right ascension and declination from the header in the fits file.
For the final image dimensions, I calculate the distance between x1 and x2 and create a new image that is 1/2 image 1 width + distance + 1/2 image 2 width. For the final height I do a similar calculation with y and image heights.
The images do also have a rotational component, but I am ignoring that as both images share the same rotation. This could be part of my problem.
public const double PixelsPerArcSecond = .039; // per WFC3 spec from Nasa
public static ImageDataModel Combine(List<ImageDataModel> inputImages)
{
// Right ascension is CRVAL1
// Declination is CRVAL2
// formula is (since distance is the same for everything):
// x = cos(dec) * cos(ra)
// y = cos(dec) * sin(ra)
ImageDataModel returnImage = new ImageDataModel();
ImageDataModel bm = inputImages[0];
double x1, y1, x2, y2;
x1 = Math.Cos(bm.CRVAL2) * Math.Cos(bm.CRVAL1);
y1 = Math.Cos(bm.CRVAL2) * Math.Sin(bm.CRVAL1);
int mult = 4; // todo: set this based off of the bitpix of the incoming images.
for (int i = 1; i < inputImages.Count; i++)
{
ImageDataModel cm = inputImages[i];
x2 = Math.Cos(cm.CRVAL2) * Math.Cos(cm.CRVAL1);
y2 = Math.Cos(cm.CRVAL2) * Math.Sin(cm.CRVAL1);
double dx = x1 - x2;
double dy = y1 - y2;
int distX = (int)((dx * 3600) / PixelsPerArcSecond);
int distY = (int)((dy * 3600) / PixelsPerArcSecond);
// This is what I expect to be wider than tall, but the converse is true.
int w = Math.Abs(distX) + (bm.ImageWidth / 2) + (cm.ImageWidth / 2);
int h = Math.Abs(distY) + (bm.ImageHeight / 2) + (cm.ImageHeight / 2);
// This is where the two images are combined into the final image.
ImageDataModel imd = CombineTwoImages(bm, cm, i, w, h, mult);
bm = imd;
}
return returnImage;
}
I am expecting an image that turns out like this:
http://wierdling.net/stack-overflow-images/ManuallyCombined.png
But getting this:
http://wierdling.net/stack-overflow-images/CombinedTest.png
The stats for the first image are: Width = 4139, Height = 4535, RA = 350.1584456860353 (CRVAL1), DEC = 61.16155335032816 (CRVAL2), ORIENTAT = -125
The stats for the second image are:Width = 4139, Height = 4535, RA = 350.1159150008405 (CRVAL1), DEC = 61.19543100394401 (CRVAL2), ORIENTAT = -125
The final expected width is close to 7733 with a height near 4773.
The final actual width is 4284, and the height is 7662.
Does anyone have any insight into what I am doing wrong?
The full source code for the program can be downloaded from https://bitbucket.org/wierdling/fitscombiner/src/master/
It currently only works with WFC3 data, and the program is very much a work in progress.
I think that your image program already does the rotation and you should do it too.
If I rotate the coordinates you calculated by 125 degrees and then calculate how far away the coordinate x1 is from the left side and the same for x2 and the y coordiantes I get a width of 6725 and height of 6166.
Not perfect but I think it goes in the right direction.
Hope that helped.
public static ImageDataModel Combine(List<ImageDataModel> inputImages)
{
// Right ascension is CRVAL1
// Declination is CRVAL2
// formula is (since distance is the same for everything):
// x = cos(dec) * cos(ra)
// y = cos(dec) * sin(ra)
ImageDataModel returnImage = new ImageDataModel();
ImageDataModel bm = inputImages[0];
double x1, y1, x2, y2;
x1 = Math.Cos(bm.CRVAL2) * Math.Cos(bm.CRVAL1);
y1 = Math.Cos(bm.CRVAL2) * Math.Sin(bm.CRVAL1);
var values = Rotate(0 - bm.Orientation, x1, y1);
x1 = values.x;
y1 = values.y;
int mult = 4; // todo: set this based off of the bitpix of the incoming images.
for (int i = 1; i < inputImages.Count; i++)
{
ImageDataModel cm = inputImages[i];
x2 = Math.Cos(cm.CRVAL2) * Math.Cos(cm.CRVAL1);
y2 = Math.Cos(cm.CRVAL2) * Math.Sin(cm.CRVAL1);
var values2 = Rotate(0 - bm.Orientation, x2, y2);
x2 = values2.x;
y2 = values2.y;
double dx = x1 - x2;
double dy = y1 - y2;
int distX = (int)((dx * 3600) / PixelsPerArcSecond);
int distY = (int)((dy * 3600) / PixelsPerArcSecond);
double width = (1.0 + x1) * (bm.ImageWidth / 2) + (1.0 - x2) * (cm.ImageWidth / 2) + Math.Abs(distX);
double height = (1.0 + y1) * (bm.ImageHeight / 2) + (1.0 - y2) * (cm.ImageHeight / 2) + Math.Abs(distY);
// This is what I expect to be wider than tall, but the converse is true.
int w = Math.Abs(distX) + (bm.ImageWidth / 2) + (cm.ImageWidth / 2);
int h = Math.Abs(distY) + (bm.ImageHeight / 2) + (cm.ImageHeight / 2);
// This is where the two images are combined into the final image.
ImageDataModel imd = CombineTwoImages(bm, cm, i, w, h, mult);
bm = imd;
}
return returnImage;
}
private static (double x, double y) Rotate(int angle, double x, double y)
{
double rad = Math.PI * angle / 180.0;
return (x * Math.Cos(rad) - y * Math.Sin(rad), x * Math.Sin(rad) + y * Math.Cos(rad));
}
i i am relative new to c# and is trying to draw a curved line in c#. I would like to ask that is there any possible way to create an X and Y axis in order to show the coordinates of each point of the curved line.
Please do help me on this matter as i am stuck on how to execute it.
protected override void OnPaint(PaintEventArgs e)
{
float a = 1, b = 5, c = 1;
double x1, x2, x3,x4,x5,x6, y1, y2, y3,y4,y5, delta;
delta = (b * b) - (4 * a * c);
x1=0;
y1 = a * (x1 * x1) + (b * (x1)) + c;
x2 = 3;
y2 = a * (x2 * x2) + (b * (x2)) + c;
x3 = - 3;
y3 = a * (x3 * x3) + (b * (x3)) + c;
x4 = 5;
y4 = a * (x4 * x4) + (b * (x4)) + c;
x5 = -10;
y5 = a * (x5 * x5) + (b * (x5)) + c;
int cx1 = Convert.ToInt32(x1);
int cx2 = Convert.ToInt32(x2);
int cx3 = Convert.ToInt32(x3);
int cy1 = Convert.ToInt32(y1);
int cy2 = Convert.ToInt32(y2);
int cy3 = Convert.ToInt32(y3);
int cx4 = Convert.ToInt32(x4);
int cy4 = Convert.ToInt32(y4);
int cx5 = Convert.ToInt32(x5);
int cy5 = Convert.ToInt32(y5);
Graphics g = e.Graphics;
int deltaX = 100;
int deltaY = 100;
g.TranslateTransform(deltaX, deltaY);
float factor = 2.5f;
Matrix m = new Matrix();
m.Scale(factor, factor);
g.MultiplyTransform(m);
Pen aPen = new Pen(Color.Blue, 1);
Point point1 = new Point(cx1, cy1);
Point point2 = new Point(cx2, cy2);
Point point3 = new Point(cx3, cy3);
Point point4 = new Point(cx4, cy4);
Point point5 = new Point(cx5, cy5);
Point[] Points = { point5, point3, point1,point2,point4 };
g.DrawCurve(aPen, Points);
Maybe I misunderstand you, but it sounds like you want to make your GDI+ graphics scale with the window size (i.e. you want to scale the X and Y axis with the size of the window), right?
This is pretty simple, you just have to decide how big of a space you want to present in the window -- i.e. if you want to make the axis go from 0,0 on the top left, to 512x512 on the bottom right, then you would just need to scale the X axis by a factor of 512/width, and the Y axis by a factor of 512/height.
So you would do that by performing a ScaleTransform on your Graphics object. You'll need to use your Form's ClientSize to get the width and height. (The regular Form's .Width, and .Height properties, include all the borders and title bars, padding pixels, etc. -- so it's no good for this calculation.)
Then you will need to force an Invalidation during the form's Resize event (it will work without this, when you make the window smaller, but when you make it bigger, this will be required, or else it will only redraw the edges).
Another thing worth considering is turning on the form's DoubleBuffered property, the redraw will be much smoother.
So, let's assume you want to work in a virtual space of 512x512 "pixels" where 0 ,0 is always the top left, and 512,512 is the bottom right. You could add this code to the top of your OnPaint event handler:
float scaleX = 512f / ((float)this.ClientSize.Width);
float scaleY = 512f / ((float)this.ClientSize.Height);
e.Graphics.ScaleTransform(scaleX, scaleY);
Then add a handler for the Form's Resize event and add something like this:
this.Invalidate(true);
That should do the trick.
I'm creating a silverlight application where I have to dynamically create buttons. But I need to place them in a circle around the button that I click to generate the other buttons (picture here, the buttons should go on the black line surrounding the 'test project' button)
I don't know how many buttons will be generated each time but I do know the size of each button is static. I'm not quite sure how to do this. Currently my button creation is as follows
foreach (Item a in itemList)
{
Button newButton = new Button();
newButton.Height = 50;
newButton.Width = 50;
newButton.Content = a.getName();
newButton.Click += new RoutedEventHandler(addedClick);
newButton.HorizontalAlignment = HorizontalAlignment.Left;
newButton.VerticalAlignment = VerticalAlignment.Top;
newButton.Margin = new Thickness(0, 0, 0, 0);
newButton.Style = (Style)Application.Current.Resources["RB"];
buttons.Add(newButton);
}
My biggest problem is that I'm not quite sure how to get the center point of the 'test project' button.
EDIT: Okay, now that I have a set of coordinates for each button, how exactly do I go about placing them? I'm not sure how to use a canvas. I tried to set one up but it keeps acting like a stackpanel (no .setLeft/.setTop).
You mean something like the circle equation:
Double distanceFromCenter = 5;
Double angleInDegrees = 90;
Double angleAsRadians = (angleInDegrees* Math.PI) / 180.0;
Double centerX = 100;
Double centerY = 100;
Double x = centerX + Math.Cos(angleAsRadians) * distanceFromCenter;
Double y = centerY + Math.Sin(angleAsRadians) * distanceFromCenter;
that should give you a point that is distanceFromCenter units away from (centerX, center), at an angle of 90-degrees. Note this only works with radians so we have to convert to radians.
var radius = 100;
var angle = 360 / itmeList.Count * Math.PI / 180.0f;
var center = new Point(100, 100);
for (int i = 0; i < itemList.Count; i++)
{
var x = center.X + Math.Cos(angle * i) * radius;
var y = center.Y + Math.Sin(angle * i) * radius;
Button newButton = new Button();
newButton.RenderTransformOrigin = new Point(x, y);
newButton.Height = 50;
newButton.Width = 50;
newButton.Content = a.getName();
newButton.Click += new RoutedEventHandler(addedClick);
newButton.HorizontalAlignment = HorizontalAlignment.Left;
newButton.VerticalAlignment = VerticalAlignment.Top;
newButton.Margin = new Thickness(0, 0, 0, 0);
newButton.Style = (Style)Application.Current.Resources["RB"];
buttons.Add(newButton);
}
Assuming you want your buttons evenly spaced on the circle, you should first generate the list of angles you want them at. E.g.
double eachSection = 2 * Math.PI / count;
var anglesInRadians = Enumerable.Range(0, count).Select(x => x * eachSection);
Then use this formula to find the x/y coordinates of each angle, and use a Canvas or something to position the buttons in those positions
public static Point PointOnCircle(double radius, double angleInRadians, Point origin)
{
double x = radius * Math.Cos(angleInRadians) + origin.X;
double y = radius * Math.Sin(angleInRadians) + origin.Y;
return new Point(x, y);
}
I'm using ZedGraph in my project and its awesome! But there is still one thing I can't figure out. Im looking for some possibility of plotting description of LineItem directly in chart, like on fig.:
http://www.imagesup.net/?di=113548312290
I tried to use TextObj, but still I have a problem correctly calculate the angle, it doesnt correspond to the slope of line. Can anyone tell my whats wrong? PS: maybe this could be caused by different ranges of X- and Y-Axis, or different length of these axes on the screen?
PointPair ptA = new PointPair(0, 100);
PointPair ptB = new PointPair(100, 0);
PointPairList ppl = new PointPairList();
ppl.Add(ptA);
ppl.Add(ptB);
LineItem myCurve = zedGraphControl1.GraphPane.AddCurve(string.Empty, ppl, Color.Red, SymbolType.Circle);
// centre of line
PointPair pt = new PointPair(0.5 * (ptA.X + ptB.X), 0.5 * (ptA.Y + ptB.Y));
TextObj text = new TextObj("desc", pt.X, pt.Y, CoordType.AxisXYScale, AlignH.Center, AlignV.Center);
text.ZOrder = ZOrder.A_InFront;
double dX = ptB.X - ptA.X;
double dY = ptB.Y - ptA.Y;
float alfa = (float)(Math.Atan2(dY, dX) * (180.0 / Math.PI));
text.FontSpec.Angle = alfa;
zedGraphControl1.GraphPane.GraphObjList.Add(text);
zedGraphControl1.AxisChange();
zedGraphControl1.Invalidate();
zedGraphControl1.Refresh();
// Call this method from the Form_Load method, passing your ZedGraphControl
public void CreateChart( ZedGraphControl zgc )
{
GraphPane myPane = zgc.GraphPane;
// Set the titles and axis labels
myPane.Title.Text = "Demo of Labeled Points";
myPane.XAxis.Title.Text = "Time, Seconds";
myPane.YAxis.Title.Text = "Pressure, Psia";
// Build a PointPairList with points based on Sine wave
PointPairList list = new PointPairList();
const int count = 15;
for ( int i = 0; i < count; i++ )
{
double x = i + 1;
double y = 21.1 * ( 1.0 + Math.Sin( (double)i * 0.15 ) );
list.Add( x, y );
}
// Hide the legend
myPane.Legend.IsVisible = false;
// Add a curve
LineItem curve = myPane.AddCurve( "label", list, Color.Red, SymbolType.Circle );
curve.Line.Width = 2.0F;
curve.Line.IsAntiAlias = true;
curve.Symbol.Fill = new Fill( Color.White );
curve.Symbol.Size = 7;
// Fill the axis background with a gradient
myPane.Chart.Fill = new Fill( Color.White, Color.FromArgb( 255, Color.ForestGreen ), 45.0F );
// Offset Y space between point and label
// NOTE: This offset is in Y scale units, so it depends on your actual data
const double offset = 1.0;
// Loop to add text labels to the points
for ( int i = 0; i < count; i++ )
{
// Get the pointpair
PointPair pt = curve.Points[i];
// Create a text label from the Y data value
TextObj text = new TextObj( pt.Y.ToString( "f2" ), pt.X, pt.Y + offset,
CoordType.AxisXYScale, AlignH.Left, AlignV.Center );
text.ZOrder = ZOrder.A_InFront;
// Hide the border and the fill
text.FontSpec.Border.IsVisible = false;
text.FontSpec.Fill.IsVisible = false;
//text.FontSpec.Fill = new Fill( Color.FromArgb( 100, Color.White ) );
// Rotate the text to 90 degrees
text.FontSpec.Angle = 90;
myPane.GraphObjList.Add( text );
}
// Leave some extra space on top for the labels to fit within the chart rect
myPane.YAxis.Scale.MaxGrace = 0.2;
// Calculate the Axis Scale Ranges
zgc.AxisChange();
}
Source: http://zedgraph.dariowiz.com/index9769.html?title=Point_Label_Demo
I have the same issue. Here's a partial solution I worked up in VB; should be easy enough to translate to C#:
' Calc deltas for x and y
Dim dX As Double = ptB.X - ptA.X
Dim dY As Double = ptB.Y - ptA.Y
' compensate delta x for graph resizing, which affects line slopes
Dim resizeCompensation As Double = 1.0 / (myPane.XAxis.Scale.Max - myPane.XAxis.Scale.Min)
dX = dX * resizeCompensation
' now calculate angle
Dim alfa As Double = Math.Atan2(dY, dX) * (180.0 / Math.PI)
text.FontSpec.Angle = alfa
While the above worked well enough for my purposes, a more comprehensive solution might be had here:
http://sourceforge.net/p/zedgraph/discussion/392232/thread/0d261bc7/