How to get coordinate on the chart - activex

I have used following way to get x-axis and y-axis co-ordinate. But I'm unable to get y axis co-ordinates.
**/*X axis max*/**
double xMaxAxisBottom = m_Chart.GetAxis().GetBottom().GetMaximum();// try to get x axis
double xMaxAxisBottomPixelPos = m_Chart.GetAxis().GetBottom().CalcXPosValue(xMaxAxisBottom); // Here trying to position based on x-axis co-ordinate
**/*X axis min*/**
double xMinAxisBottom = m_reschedChart.GetAxis().GetBottom().GetMinimum();//// try to get x axis minimum
double xMinAxisBottomPixelPos = m_Chart.GetAxis().GetBottom().MinXValue();
**/*Y axis max*/**
double xMaxAxisLeft = m_reschedChart.GetAxis().GetLeft().GetMaximum();
double xMaxAxisLeftPixelPos = m_reschedChart.GetAxis().GetLeft().MaxXValue();
**/*Y axis min*/**
double xMinAxisLeft = m_Chart.GetAxis().GetLeft().GetMinimum();
double xMinAxisLeftPixelPos = m_Chart.GetAxis().GetLeft().MinXValue();
**/*X axis length*/**
double xAxisBottomLen = m_Chart.GetAxis().GetBottom().GetEndPosition() - m_Chart.GetAxis().GetBottom().GetStartPosition();
double xAxisBottomLenPixelPos = m_Chart.GetAxis().GetBottom().CalcXPosValue(xAxisBottomLen);
**/*Y axis length*/**
double yAxisLeftLen = m_Chart.GetAxis().GetLeft().GetEndPosition() - m_Chart.GetAxis().GetLeft().GetStartPosition();
double xAxisLeftLenPixelPos = m_Chart.GetAxis().GetBottom().CalcXPosValue(yAxisLeftLen);
**/*X origin*/**
double dXstartPos = m_Chart.GetAxis().GetBottom().GetStartPosition();
double dXstartPixelPos = m_reschedChart.GetAxis().GetBottom().CalcXPosValue(dXstartPos);
**/*Y origin*/**
double dYStartPos = m_Chart.GetAxis().GetLeft().GetStartPosition();
double dYStartPixelPos = m_Chart.GetAxis().GetLeft().CalcXPosValue(dYStartPos);
let me know if i am making any mistake to find the co-ordinates.
I wanted to find below mention co-ordinated using above code.
1 X axis max
2 X axis min
3 Y axis max
4 Y axis min
5 X axis length
6 Y axis length
7 X origin
8 Y origin
9 Label font size
Please let me know your view.
Thanks

The chart needs to be drawn to use these methods. They need some internal properties to be initialized to work as expected.
You can force a chart repaint before calling them with:
m_Chart.GetEnvironment().InternalRepaint();
EDIT:
Since you seem to be calling these functions at OnAfterDraw event, you don't need to force a chart repaint. However, I'd suggest you some modifications in your code.
I see you are using m_Chart and also m_reschedChart. Make sure you are using the correct TChart variable.
Your variables start with x and y but thay also include Bottom or Left depending on the axis they refer. This is redundant and increments the chances to write a mistake (ie xMaxAxisLeft).
CalcXPosValue has to be used with Horizontal axes and CalcYPosValue with Vertical axes. So you shouldn't call GetLeft().CalcXPosValue.
CalcXPosValue and CalcYPosValue are functions to convert axis values to screen pixels.
MinXValue and MaxXValue are to be used with Horizontal Axes while MinYValue and MaxYValue are to be used with Vertical Axes.
GetMinimum returns the same than MinXValue/MinYValue, and GetMaximum returns the same than MaxXValue/MaxYValue. All these functions return Axis values, not screen pixels.
GetStartPosition and EndStartPosition are thought to modify the Axis length and by default they use percentages as explained here, so GetStartPosition - EndStartPosition is always zero. And I think CalcXPosValue(GetStartPosition - EndStartPosition) is conceptually wrong too. Note IStartPos and IEndPos give you the Start and End positions in pixels. See the TeeChart ActiveX Tutorials here.
Find below the modified code I suggest you:
**/*X axis max*/**
double maxAxisBottom = m_Chart.GetAxis().GetBottom().GetMaximum();// try to get x axis
double maxAxisBottomPixelPos = m_Chart.GetAxis().GetBottom().CalcXPosValue(xMaxAxisBottom); // Here trying to position based on x-axis co-ordinate
**/*X axis min*/**
double minAxisBottom = m_Chart.GetAxis().GetBottom().GetMinimum();//// try to get x axis minimum
double minAxisBottomPixelPos = m_Chart.GetAxis().GetBottom().CalcXPosValue(minAxisBottom);
**/*Y axis max*/**
double maxAxisLeft = m_Chart.GetAxis().GetLeft().GetMaximum();
double maxAxisLeftPixelPos = m_Chart.GetAxis().GetLeft().CalcYPosValue(maxAxisLeft);
**/*Y axis min*/**
double minAxisLeft = m_Chart.GetAxis().GetLeft().GetMinimum();
double minAxisLeftPixelPos = m_Chart.GetAxis().GetLeft().CalcYPosValue(minAxisLeft);
Now you already know the position of the four squares in screen pixels so you can ie draw a rectangle using them to check it:
m_Chart.getCanvas().Rectangle(minAxisBottomPixelPos, minAxisLeftPixelPos, maxAxisBottomPixelPos, maxAxisLeftPixelPos);
If you also want or need the sizes of the axes in pixels, you can do:
**/*X axis length*/**
double axisBottomLenPixelPos = m_Chart.GetAxis().GetBottom().GetIEndPos() - m_Chart.GetAxis().GetBottom().GetIStartPos();
**/*Y axis length*/**
double axisLeftLenPixelPos = m_Chart.GetAxis().GetLeft().GetIEndPos() - m_Chart.GetAxis().GetLeft().GetIStartPos();
And you can check they are correctly calculated:
m_Chart.getCanvas().Rectangle minAxisBottomPixelPos, maxAxisLeftPixelPos, minAxisBottomPixelPos + axisBottomLenPixelPos, maxAxisLeftPixelPos + axisLeftLenPixelPos

Related

What does the param "axis" do in Scale Layer

I understand that Scale Layer works as z = x * y where y is "broadcasted" to match the shape of x.
Here is my question:
I have bottom[0] size as N*C*H*W, with bottom[1] as N*1*H*W,
and I want to tile bottom[1] to N*C*H*W, then computing the element-wise product.
How should I set the parameters, especially "axis"?
Thx a lot.
Based on scale_layer.cpp axis is the starting axis for scaling:
axis_ = bottom[0]->CanonicalAxisIndex(param.axis());
...
const vector<int>::const_iterator& shape_start =
bottom[0]->shape().begin() + axis_;
const vector<int>::const_iterator& shape_end =
(num_axes == -1) ? bottom[0]->shape().end() : (shape_start + num_axes);
vector<int> scale_shape(shape_start, shape_end);
So, in your case you can set axis parameter to either 0 or 1.
There is also another parameter num_axis, which from my understanding, is the number of axes that are scaled. In your case, it can be set to 2 or 1 depending on you axis parameter. (axis=1, num_axis=1 or axis =0, num_axis=2).
I have never used this layer, and these conclusions are only based on the source code of scale_layer.
I am not hundred percent sure. But you could try two things. In concat layer, axis = 0, means the first dimension(N) in your N * C * H * W, and axis = 1, means second dimension (C). so you could try with axis = 1, and scale parameter of 3. I am not completely sure. But you could try and let me know what you get.
Another thing you can try is to use Concat layer with axis = 1.

How to fix a gap between the x and y axes in core plot

I am using [_graph.defaultPlotSpace scaleToFitPlots:[_graph allPlots]];
and if where none of the plots has a y value of 0, there is a gap between the bottom of the Y axis and the X axis.
I've tried using _graph.axisSet.xAxis.orthogonalCoordinateDecimal = CPTDecimalFromDouble(0.0);
as well as a calculated yMin instead of 0.0.
Yet, I still get this:
I've also tried to rescale the plot space, thus:
[_graph.defaultPlotSpace setPlotRange:r forCoordinate:CPTCoordinateY];
but couldn't figure out how to set a new minLimit for r.
Use the axisConstraints to position the x-axis at the lower edge of the plot area:
x.axisConstraints = [CPTConstraints constraintWithLowerOffset:0.0];

Rounding Corners: How to calculate Fillet radius?

How do I find the maximum rounding I can apply to either corner for any amount of rounding on the other corner?
Answers to questions from the comments:
1) The inner and outer large arcs (those that are 90 degrees wide here) always have the same center
2) When asking for the maximum rounding that you can do, what are the constraints on the other, smaller circle? Does it need to be at least some radius? Otherwise you are doing to end up with just one rounding.
One of the two rounding circle's radius is given. There are no other constraints other than the maximum of the other circle which I just can't find.
If the "fixed" corner that I refer to has zero rounding then I'm searching for the maximum rouding that can be applied with only the other corner.
3) What constitutes as the maximum rounding? Are you trying to choose between the two examples above? Or is finding either of those cases considered a solution?
Either of the shown cases is a perfect solution. E.g. in the first image the the radius of the smaller circle might be given. Then I'm looking for the maximum radius of the larger one.
These images are just examples for perfect solutions.
4) is there any constraints on the two arcs? What happens if the arcs can't fit a full circle? Would the answer be the largest that fits?
How exactly do you mean that the arcs can't fit a full circle?
The all circles are perfect circles, but I can't figure out the max size of the rounding possible, or how to calculate it's position. Here's some images that describe the problem.
Given that the origin of the coordinate system is at the center point of the inner and outer large arcs...
For the first case where the large circle is tangent to the outer edge, the center point of the large circle is
x = R cos(t) / (1 + cos(t))
y = R sin(t) / (1 + cos(t))
where R is the radius of the outer arc segment, and t is the angle between the x-axis and the ray from the origin through the center of the large circle.
For the second case where the large circle is tangent to the inner edge, the center point of the large circle is
x = R cos(t) / (1 - cos(t))
y = R sin(t) / (1 - cos(t))
where R is the radius of the inner arc segment, and t is the angle...
In both cases, the radius of the circle is equal to its x coordinate. The range of t is between some minimum angle and PI/2. At PI/2, the circle is vanishingly small. At the minimum angle, the y value is equal to the opposite radius. In other words, for the first case where the large circle is tangent to the outer edge, the minimum angle is such that y is equal to the inner radius. Whereas if the circle is tangent to the inner edge, the minimum angle is such that y is equal to the outer radius. It can be proven mathematically that the minimum angle is the same for both cases (tangent to inner and tangent to outer both have the same minimum angle for a given inner and outer radius). However, computing the minimum angle is a bit of a challenge. The only way I know how to do it is by playing the high/low game, e.g.
- (CGFloat)computeAngleForOuterTangentGivenY:(CGFloat)Y
{
CGFloat y;
double high = M_PI_2;
double low = 0;
double mid = M_PI_4;
while ( high - low > 1e-9 )
{
y = (self.outerRadius * sin( mid )) / (1.0 + cos( mid ));
if ( y > Y )
high = mid;
else
low = mid;
mid = (low + high) / 2.0;
}
return( mid );
}
- (CGFloat)computeAngleForInnerTangentGivenY:(CGFloat)Y
{
CGFloat y;
double high = M_PI_2;
double low = 0;
double mid = M_PI_4;
while ( high - low > 1e-9 )
{
y = (self.innerRadius * sin( mid )) / (1.0 - cos( mid ));
if ( y > Y )
low = mid;
else
high = mid;
mid = (low + high) / 2.0;
}
return( mid );
}
It takes about 30 passes for the loop to converge to an answer.
To find the coordinates of the small circle, note that the small circle has the same y value as the large circle, and is tangent to the opposite edge of the arc segment. Therefore, compute the angle t for the small circle based on its y value using the appropriate high/low algorithm, and then compute the x value using the formulas above.
QED
The question isn't posed correctly without showing both ends of the line segment. Suppose for a moment that each line segment is a data structure that maintains not only the end points, but also cap radius in each point, and also knows the angle going out to the next endpoint that this line will attach to. Each cap radius will subtract from the length of the line segment that has to be stroked as a rectangle. Assume you have a line of interest between points B and C, where B joins to another (longer) segment A, and C joins to another (longer) segment D. If line BC is length 10, with cap radius B and cap radius C both set to 4, then you will only render rectangle of length 2 for the straight part of the line segment, while length 4 is used to draw the arc to A, and another length 4 is used to draw the arc to D.
Furthermore, the maximum cap radius for C is constrained not only by BC and B's cap radius, but also by CD and D's cap radius.

OpenGL: How to lathe a 2D shape into 3D?

I have an OpenGL program (written in Delphi) that lets user draw a polygon. I want to automatically revolve (lathe) it around an axis (say, Y asix) and get a 3D shape.
How can I do this?
For simplicity, you could force at least one point to lie on the axis of rotation. You can do this easily by adding/subtracting the same value to all the x values, and the same value to all the y values, of the points in the polygon. It will retain the original shape.
The rest isn't really that hard. Pick an angle that is fairly small, say one or two degrees, and work out the coordinates of the polygon vertices as it spins around the axis. Then just join up the points with triangle fans and triangle strips.
To rotate a point around an axis is just basic Pythagoras. At 0 degrees rotation you have the points at their 2-d coordinates with a value of 0 in the third dimension.
Lets assume the points are in X and Y and we are rotating around Y. The original 'X' coordinate represents the hypotenuse. At 1 degree of rotation, we have:
sin(1) = z/hypotenuse
cos(1) = x/hypotenuse
(assuming degree-based trig functions)
To rotate a point (x, y) by angle T around the Y axis to produce a 3d point (x', y', z'):
y' = y
x' = x * cos(T)
z' = x * sin(T)
So for each point on the edge of your polygon you produce a circle of 360 points centered on the axis of rotation.
Now make a 3d shape like so:
create a GL 'triangle fan' by using your center point and the first array of rotated points
for each successive array, create a triangle strip using the points in the array and the points in the previous array
finish by creating another triangle fan centered on the center point and using the points in the last array
One thing to note is that usually, the kinds of trig functions I've used measure angles in radians, and OpenGL uses degrees. To convert degrees to radians, the formula is:
degrees = radians / pi * 180
Essentially the strategy is to sweep the profile given by the user around the given axis and generate a series of triangle strips connecting adjacent slices.
Assume that the user has drawn the polygon in the XZ plane. Further, assume that the user intends to sweep around the Z axis (i.e. the line X = 0) to generate the solid of revolution, and that one edge of the polygon lies on that axis (you can generalize later once you have this simplified case working).
For simple enough geometry, you can treat the perimeter of the polygon as a function x = f(z), that is, assume there is a unique X value for every Z value. When we go to 3D, this function becomes r = f(z), that is, the radius is unique over the length of the object.
Now, suppose we want to approximate the solid with M "slices" each spanning 2 * Pi / M radians. We'll use N "stacks" (samples in the Z dimension) as well. For each such slice, we can build a triangle strip connecting the points on one slice (i) with the points on slice (i+1). Here's some pseudo-ish code describing the process:
double dTheta = 2.0 * pi / M;
double dZ = (zMax - zMin) / N;
// Iterate over "slices"
for (int i = 0; i < M; ++i) {
double theta = i * dTheta;
double theta_next = (i+1) * dTheta;
// Iterate over "stacks":
for (int j = 0; j <= N; ++j) {
double z = zMin + i * dZ;
// Get cross-sectional radius at this Z location from your 2D model (was the
// X coordinate in the 2D polygon):
double r = f(z); // See above definition
// Convert 2D to 3D by sweeping by angle represented by this slice:
double x = r * cos(theta);
double y = r * sin(theta);
// Get coordinates of next slice over so we can join them with a triangle strip:
double xNext = r * cos(theta_next);
double yNext = r * sin(theta_next);
// Add these two points to your triangle strip (heavy pseudocode):
strip.AddPoint(x, y, z);
strip.AddPoint(xNext, yNext, z);
}
}
That's the basic idea. As sje697 said, you'll possibly need to add end caps to keep the geometry closed (i.e. a solid object, rather than a shell). But this should give you enough to get you going. This can easily be generalized to toroidal shapes as well (though you won't have a one-to-one r = f(z) function in that case).
If you just want it to rotate, then:
glRotatef(angle,0,1,0);
will rotate it around the Y-axis. If you want a lathe, then this is far more complex.

Get map position when WGS-84 lat/lon when upper left and lower right corners' lat/lon are given

Suppose I have a map, for example from openstreetmaps.org.
I know the WGS-84 lat/lon of the upper left and lower right corner of the map.
How can I find other positions on the map from given WGS-84 lat/lon coordinates?
If the map is roughly street/city level, uses a mercator projection (as openstreetmap.org seems to), and isn't too close to the poles, linear interpolation may be accurate enough. Assuming the following:
TL = lat/lon of top left corner
BR = lat/lon of bottom right corner
P = lat/lon of the point you want to locate on the map
(w,h) = width and height of the map you have (pixels?)
the origin of the map image, (0,0), is at its top-left corner
, we could interpolate the (x,y) position corresponding to P as:
x = w * (P.lon - TL.lon) / (BR.lon - TL.lon)
y = h * (P.lat - TL.lat) / (BR.lat - TL.lat)
Common gotcha's:
The lat/lon notation convention lists the latitude first and the longitude second, i.e. "vertical" before "horizontal". This is opposite to the common x,y notation of image coordinates.
Latitude values increase when going in a north-ward direction ("up"), whereas y coordinates in your map image may be increasing when doing down.
If the map covers a larger area, linear interpolation will not be as accurate for latitudes. For a map that spans one degree of latitude and is in the earth's habitable zones (e.g. the bay area), the center latitude will be off by 0.2% or so, which is likely to by less than a pixel (depending on size)
If that's precise enough for your needs, you can stop here!
The more precise math for getting from P's latitude to a pixel y position would start with the mercator math. We know that for a latitude P.lat, the Y position on a projection starting at the equator would be as follows (I'll use a capital Y as unlike the y value we're looking for, Y starts at the equator and increases towards the north):
Y = k * ln((1 + sin(P.lat)) / (1 - sin(P.lat)))
The constant k depends on the vertical scaling of the map, which we may not know. Luckily, it can be deduced observing that y(TL) - y(BR) = h. That gets us:
k = h / (ln((1 + sin(TL.lat)) / (1 - sin(TL.lat))) - ln((1 + sin(BR.lat)) / (1 - sin(BR.lat))))
(yikes! that's four levels of brackets!) With k known, we now have the formula to find out the Y position of any latitude. We just need to correct for: (1) our y value starts at TL.lat, not the equator, and (2) y grows towards the south, rather than to the north. This gets us:
Y(TL.lat) = k * ln((1 + sin(TL.lat)) / (1 - sin(TL.lat)))
Y(P.lat) = k * ln((1 + sin(P.lat )) / (1 - sin(P.lat )))
y(P.lat) = -(Y(P.lat) - Y(TL.lat))
So this gets you:
x = w * (P.lon - TL.lon) / (BR.lon - TL.lon) // like before
y = -(Y(P.lat) - Y(TL.lat)) // where Y(anything) depends just on h, TL.lat and BR.lat

Resources