When would you use AffineTransform getScaleX()? - java

Is there a legitimate use case for AffineTransform.getScaleX() and family?
It returns the m00 or the top left corner element of the transform matrix and that is pretty useless for determining the scaling the matrix does. Consider for example a trivial 90 degree rotation matrix and both getScaleX() and getScaleY() return 0.
I would never use this call as it is confusing to the code reader who may not be familiar with the fact that it does not return scaling in a meaningful way, much better to getMatrix(m) and then access the m[0], because most people likely to read code that uses transformations are familiar with matrix math.
There must be a use case for this, but I just don't get it.

As you wrote, the notion of the x scaling factor is quite meaningless in the general case. It is only relevant for the special case of scaling matrixes. i.E. those for which getType returns TYPE_GENERAL_SCALE or TYPE_UNIFORM_SCALE. (A translation could be added, too) In other cases, getScaleX is "correct" in the sense that it does what the docs say, but usesless and misleading regarding its name. Analogous reasoning applies to getShearX, which only makes senses in context of shearing matrixes. getTranslateX is a bit different, since one could argue that this is where the origin gets translated to, regardless of all other transformations the matrix implies.

Related

The user input for a calculating the tangent of a graph

I am making a program that calculates the equation for the tangent of a graph at a given point and ideally I'd want it to work for any type of graph. e.g. 1/x ,x^2 ,ln(x), e^x, sin, tan. I know how to work out the tangent and everything but I just don't really know how to get the input from the user.
Would I have to have options where they choose the type of graph and then fill in the coefficients for it e.g. "Choice 1: 1/(Ax^B) Enter the values of A and B"? Or is there a way so that the program recognises what the user types in so that instead of entering a choice and then the values of A and B, the user can type "1/3x^2" and the program would recognise that the A and B are 3 and 2 and that the graph is a 1/x graph.
This website is kind of an example of what I would like to do be able to do: https://www.symbolab.com/solver/tangent-line-calculator
Thanks for any help :)
Looks like you want to evalute the expression. In that case, you could look into Dijkstra's Shunting-Yard algorithm to convert the expression to prefix notation, and then evaluate the expression using stacks. Alternatively, you can use a library such as exp4j. There are multiple tutorials for it, but remember that you need to add operations for both binary and unary operations (binary meaning it supports 2 operations while unary is like sin(x)).
Then, after you evaluate the expression, you can use first principles to solve. I have an example of this system working without exp4j on my github repository. If you go back in the commit history, you can see the implementation with exp4j as well.
Parsing a formula from user input is itself a problem much harder than calculating the tangent. If this is an assignment, see if the wording allows for the choice of the functions and its parameters, as you're suggesting, because otherwise you are going to spend 10% of time writing code for calculating the derivative and 90% for reading the function from the standard input.
If it's your own idea and you'd like to try your hand at it, a teaser is that you will likely need to design a whole class structure for different operators, constants, and the unknown. Keep a stack of mathematical operations, because in 1+2*(x+1)+3 the multiplication needs to happen before the outer additions, but after the inner one. You'll have to deal with reading non-uniform input that has a high level of freedom (in whitespace, omission of * sign, implicit zero before a –, etc.) Regular expressions may be of help, but be prepared for a debugging nightmare and a ton of special cases anyway.
If you're fine with restricting your users (yourself?) to valid expressions following JavaScript syntax (which your examples are not, due to the implied multiplication and the haphazard rules of precedence thereof to the 1/...) and you can trust them absolutely in having no malicious intentions, see this question. You wouldn't have your expression represented as a formula internally, but you would still be able to evaluate it in different points x. Then you can approximate the derivative by (f(x+ε) - f(x)) / ε with some sufficiently small ε (but not too small either, using trial and error for convergence). Watch out for points where the function has a jump, but in basic principle this works, too.

Accurate geometry in Java

I'm coding an application in Java that requires quite a lot of geometry. I made heavy use of existing classes and my calculations so far have been in double precision (so I'm using for instance, Point2D.Double, Line2D.Double and coded a convex polygon class using the latter...).
I ran into several issues relating to double precision calculations that make my application at times unstable and I considered switching to BigDecimal but that would imply creating creating my own Point2D, Line2D classes with BigDecimals etc, and rewriting several functions. Another solution would be to accept the imprecisions and deal with them; i.e. A point is actually a small square, a line is a an infinite band, a point lies on a line if the square and the band intersect and so on. Although this solution can be implemented quickly my code would be disfigured by statements like (Math.abs(x) < precision) (to signify that x == 0) scattered here and there.
Is someone aware of nice clean way to do accurate geometry in Java?
I tried to squeeze (parts of) this into a comment, but it didn't fit. You should not consider this as "THE" answer, but there are some points that I would like to list here.
The recommendation to use BigDecimal is annoyingly common whenever someone mentions precision problems with float or double - and yet is equally inappropriate in such cases as this one. In all but the fewest cases, the limited precision of double is simply not relevant.
Unless, maybe, you are writing software that should compute the trajectory of a manned spacecraft that is about to be sent to Mars, or doing other highly scientific computations.
Additionally, replacing double with BigDecimal tends to only replace one small problem with several larger ones. For example, you'll have to think about the RoundingMode and "scale", which can be tricky. And eventually, you will notice that a simple value like 1.0/3.0 can't be represented with BigDecimal either.
For your particular application case, there are more caveats:
Even with a BigDecimal-based implementation of Point2D, the data would still be exposed as double, via the getX()/getY() methods. For example, a method like Line2D#ptLineDistSq will still use the double values. This could only be avoided if you wrote everything that is related to your computations, from scratch, using BigDecimal really everywhere.
But even if you did this: You cannot compute the slope of a line from the point (-1,0) to the point (2,1), and you cannot say where this line intersects the y-axis. You might try some rational number representation here, but there's still this issue with the length of the diagonal of a unit square - which is an irrational number.
The imprecisions of double are annoying. You can compute whether a point is left of a line or right of a line. And due to the precision issues, it may well be that it is both. Doing computations with points that should "mathematically" be equal, but differ by some small floating-point error can lead to bogus results (I also stumbled over this in one of my libraries).
As you already mentioned in the question: Some concepts that work in pure mathematics have to be rethought when they should be implemented with limited precision. Any == comparison is a no-go, and other comparisons should be carefully validated, taking the possible rounding errors into account.
But using some "epsilon"-based comparisons is the usual way to deal with this. Of course, they make the code a bit more clumsy. But compare this to some "arbitrary precision" code with BigDecimal:
BigDecimal computeArea(BigDecimal radius) {
// Let's be very precise here....
BigDecimal pi = new BigDecimal("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420198938095257201065485863278865936153381827968230301952035301852968995773622599413891249721775283479131515574857242454150695950829533116861727855889075098381754637464939319");
BigDecimal radiusSquared = radius.multiply(radius);
BigDecimal area = radiusSquared.multiply(pi);
return area;
}
Vs.
double computeArea(double radius) {
return Math.PI * radius * radius;
}
Also, the epsilon-based comparisons are still error-prone and raise some questions. Most prominently: How large should this "epsilon" be? Where should the epsilon-based comparison take place? However, existing implementations, like the geometric algorithms in http://www.geometrictools.com/ might give some ideas of how this can be done (even though they are implemented in C++, and became a bit less readable in the latest versions). They are time-tested and already show how to cope with many of the precision-related problems.

Getting a gradient of a bi-variant function

I'm doing some video processing, for each frame I need to get a gradient of a bi-variate function.
The function is represented as a two dimensional array of doubles. Where the domain is the rows and columns indices and the range is the double value of the corresponding indices values. Or more simply put, the function f is defined for double[][] matrix as such:
f(x,y)=matrix[x][y]
I'm trying to use the Apache Commons Math library for it:
SmoothingPolynomialBicubicSplineInterpolator iterpolator = new SmoothingPolynomialBicubicSplineInterpolator();
BicubicSplineInterpolatingFunction f = iterpolator.interpolate(xs, ys, matrix.getData());
for (int i = 0; i < ans.length; i++) {
for (int j = 0; j < ans[0].length; j++) {
ans[i][j] = f.partialDerivativeY(i, j);
}
}
with xs, as a sorted array of the x indices (0,1,...,matrix.getRowDimension() - 1)
ys the same on the columns dimension (0,1,...,matrix.getColumnDimension() - 1)
The problem is that for a typical matrix in the size of 150X80 it takes as much as 1.4 seconds to run, which renders it completely irrelevant for my needs. So, as a novice user of this library, and programmatic numeric analysis in general, I want to know:
Am I doing something wrong?
Is there another, faster, way I can accomplish this task with?
Is there another open source library (preferably maven-friendly) that offers a solution?
Numerical differentiation is an entire topic unto itself, a simple google should bring up enough material for you to work with (just the wiki might be sufficient). There are parameters of your problem that I cannot know, so I can only speak broadly here, but there are direct methods of determining the gradient at a given point, i.e. ones that don't require an interpolation. See the wikipedia for the formulae (ranging from the simple f(x+1)-f(x), which is where h=1, to the higher order ones). Calculating the partial derivatives is then a simple O(NM) loop with an uber easy formula inside (no interpolation required).
The specifics can get gritty:
The higher order formulae need to be reduced for the edges, or
discarded altogether.
Your precise speed requirements might render more complex formulae useless (depending on the platform sometimes the lookup times for higher order formulae make them too slow; again, it depends on the cache etc.). This is easy to test, the formulae are simple; code them and benchmark.
The specific implementation is also dependent on your error requirements. The theory provides error bounds, so that will play a role in what formula you need; but again, there's a trade-off with speed requirements. The in turn can be practically lowered if you know specifics about the types of matrices you'll be processing, if such a thing is known.
The implementation can be made even easier (and maybe faster) if you have existing convolution tools, since this method is really just a convolution of the matrix (note; technically it's called a cross-correlation).

In Java, how to decide if a point is on the boundary of a GeneralPath?

I find out that the GeneralPath class in Java only provides methods to check if a point is inside a general path (to be specific, a polygon with straight line segments). Does someone know how to efficiently check if a point is on the boundary of a general path or not?
Thanks
Dummy solution 1: We can define a circle with radius $\epsilon$ ($\epsilon$ is a very small positive real value). And then, we check a sufficient number of points on the circle to see if one/some of them falls into the general path or not. However, such a dummy method may require a considerable amount of computational effort, which is not very desirable.
Dummy solution 2: We can compute the distances from the point (on the boundary) to every side of the polygon. If the minimal distance is sufficiently small, this point is on the boundary; otherwise, it is not. Again, this method can still be computationally intensive.
I haven't come across a library method ... or potted solution to the problem. I think that the reason is that the problem is fundamentally impossible to solve exactly.
The GeneralPath class inherits a method called getPathIterator from Shape2D. If you look at the javadoc, you will see that the PathIterator object models the path as a sequence of straight line segments. And the getPathIterator method takes a flatness parameter specified as follows:
"flatness - the maximum distance that the line segments used to approximate the curved segments are allowed to deviate from any point on the original curve."
Now, if the shape you are looking at consists of straight line segments, there is a good chance that the path iterator will give you those line segments. But if the shape has curved segments, then the line segments are only an approximation. And it is clearly impossible to test if a point is exactly on a boundary if you don't know what the exact boundary is.
Even assuming that the line segments exactly model the real curve, you still have the problem that (except for special cases), most of the points on the real curve cannot be represented exactly using Java primitive datatypes (int, double, etc). So once again "exactness" is problematic.
I think that the best you can hope for is to test whether your point is within some small delta of the boundary ... and choose a flatness value that is less than that delta, iterate the path line segments, and test the tangential distance of the point from each segment.
Note: if you make flatness very small, you can expect to have to test a very large number of line segments. I don't think there is any way around this computational concern while sticking to the GeneralPath API.
If you restrict the problem to true (i.e. straight-sided) polygons, then you simply need to iterate the line segments, and for each one test to see if the distance from the point to the line is less than some suitable epsilon. This Wikipedia entry gives you the mathematics. Note that exactness is still going to be a concern here ...
You don't have an enormously costly computation, but computing an accurate square-root doesn't come for free, and you have to do it up to N times for an N-sided polygon.
Doing better than that (i.e. getting better than O(N)) is going to be difficult. However, if the polygon is fixed and you are going to be testing a huge number of points against it, then you could consider using a pre-computing a quad-tree data structure to do the resolution. Precomputing the quad-tree will be expensive, but if N is large enough testing a a point will be cheaper. (Roughly O(log(1/epsilon)) in the worst case, instead of O(N) on average. And the further away from the boundary a point is, the cheaper the answer.)
But as I said, quad-trees will only help in limited situations ...
You can use stroked path. BasicStroke has method
public Shape createStrokedShape(Shape s)
So just define thick line BasicStroke, get the stroked shape and check whether the stroked Shape contains your point.

Static Typing and Writing a Simple Matrix Library

Aye it's been done a million times before, but damnit I want to do it again. I'm writing a simple Matrix Library for C++ with the intention of doing it right. I've come across something that's fairly obvious in mathematics, but not so obvious to a strongly typed system -- the fact that a 1x1 matrix is just a number. To avoid this, I started walking down the hairy path of matrices as a composition of vectors, but also stumbled upon the fact that two vectors multiplied together could either be a number or a dyad, depending on the orientation of the two.
My question is, what is the right way to deal with this situation in a strongly typed language like C++ or Java?
something that's fairly obvious in
mathematics, but not so obvious to a
strongly typed system -- the fact that
a 1x1 matrix is just a number.
That's arguable. A hardcore mathematician (I'm not) would probably argue against it, he would say that a 1x1 matrix can be regarded as isomorphic (or something like that) to a scalar, but they are conceptually different things. Only in some informal sense "a 1x1 matrix is a scalar" (similar, though stronger, that a complex number without an imaginary part "is a real").
I don't think that that correspondence should be reflected in a strong typed language. And I dont' think it is, in typical implementations (of complex or matrix), eg. Java Apache Commons Math. For example, a Complex with zero imaginary part is not a Number (from the type POV - they cannot be casted one into another).
In the case of matrices, the correspondence is even more disputable. Should we be able to multiply two matrices of sizes (4x3) x (1x1) ? If we regard the second as a scalar, it's valid, but not as a matrix, since it violates the restriction on matrix dimensions for multiplication. And I believe Commons sticks to that.
In a weakly typed language (eg Matlab) it would be another story.
If you aren't worried about SIMD optimisations and the like then I would have thought the best way would be to set up a templated tensor. Choose your maximum tensor dimensions and then you can do things like this:
typedef Tensor3D< float, 4, 1, 1 > Vector4;
And so forth. The mathematics, if implemented correctly, will just work with all forms of "matrix" and "vector". Both are, afterall, just special cases of tensors.
Edit: knowing the size of a template is actually pretty easy. Add in a GetRows() etc function and you can return the value you pass into the template at instantiation.
ie
template< typename T, int rows, int cols > class Tensor2D
{
public:
int GetRows() { return rows; }
int GetCols() { return cols; }
};
My advice? Don't worry about the 1x1 case and sleep at night. You shouldn't be worried about any uses suddenly deciding to use your library to model a bunch of numbers as 1x1 matricies and complaining about your implementation.
No one who solves these problems will be so foolish. If you're smart enough to use matricies, you're smart enough to use them properly.
As for all the permutations that scalars introduce, I'd say that you must account for them. As a matrix library user, I'd expect to be able to multiply two matricies together to get another matrix, a matrix by a (column or row) vector get a vector result, and a scalar times a matrix to get another matrix.
If I multiply two vectors I can get a scalar (inner product) or a matrix (outer product). Your library had better give them to me.
It's not trivial. It's been done "right" by others, but kudos to working it through for yourself.

Categories