Extend function defined on triangle vertexs continuously? - gradient

I have a triangle ABC in 2D space, and have defined f(A), f(B), and
f(C), where f is a real valued function. Questions:
Can I extend f to be defined on the entire triangle such that f is
continuous?
If yes, is the solution unique?
If not, can I find an f that's smooth (infinitely differentiable)
inside the triangle?
f needn't be defined outside the triangle (thus, it's OK if f isn't
continuous/differentiable at the vertexs/edges)
Goal: I want to assign rainbow colors (saturation and value both 100%,
varying hue) to the three points of a triangle, and the color the
triangle "naturally".

Related

How to create a section of cube in OpenGL [duplicate]

I'm trying to render a proper refraction/reflection in my OpenGL project and I need to use clip distance. I'm following the tutorial by Thin Matrix.
I enable the clip distance with
glEnable(GL_CLIP_DISTANCE0);
in my game loop and then I try to use it in the vertex shader like this
gl_ClipDistance[0] = -1;
I've tried to change around the -1 value but nothing happens no matter what I do. Is there something more I need to do to enable it properly?
The gl_ClipDistance array contains a series of floating-point values that represent, for each vertex, which side of a conceptual "plane" it is on. Each array index is a conceptual "plane". The vertex can be either on the negative side, or the non-negative side.
If two vertices of the same line/triangle are on two difference sides of the plane (that is, one vertex has a negative value and the other a non-negative one), then the primitive will be clipped at the location where that distance is 0. The part of the primitive on the non-negative side will be visible.
Given that, what you need to do is set up a clip distance value that represents the distance between the vertex position and the plane you want to clip against. The standard plane equation (Ax + By + Cz + D = 0) gives us a way to handle this. The distance of a point from the plane A, B, C, D, assuming the vector (A, B, C) is a unit vector, is simply:
dot(point, vec3(A, B, C)) + D
This also assumes that point is in the same space as A, B, C and D.
Of course, if point is a vec4, with the last component as 1.0, then you can just do this:
dot(point, plane);
Where plane is a vec4 that contains A, B, C, and D. And that's your clip distance.
You also need to redeclare gl_ClipDistance with an explicit size in the shader stage that uses it. In GLSL 3.20+, gl_ClipDistance lives inside an interface block, so you have to redeclare that:
out gl_PerVertex
{
vec4 gl_Position;
float gl_ClipDistance[1];
};

OpenGL Enable Clip Distance

I'm trying to render a proper refraction/reflection in my OpenGL project and I need to use clip distance. I'm following the tutorial by Thin Matrix.
I enable the clip distance with
glEnable(GL_CLIP_DISTANCE0);
in my game loop and then I try to use it in the vertex shader like this
gl_ClipDistance[0] = -1;
I've tried to change around the -1 value but nothing happens no matter what I do. Is there something more I need to do to enable it properly?
The gl_ClipDistance array contains a series of floating-point values that represent, for each vertex, which side of a conceptual "plane" it is on. Each array index is a conceptual "plane". The vertex can be either on the negative side, or the non-negative side.
If two vertices of the same line/triangle are on two difference sides of the plane (that is, one vertex has a negative value and the other a non-negative one), then the primitive will be clipped at the location where that distance is 0. The part of the primitive on the non-negative side will be visible.
Given that, what you need to do is set up a clip distance value that represents the distance between the vertex position and the plane you want to clip against. The standard plane equation (Ax + By + Cz + D = 0) gives us a way to handle this. The distance of a point from the plane A, B, C, D, assuming the vector (A, B, C) is a unit vector, is simply:
dot(point, vec3(A, B, C)) + D
This also assumes that point is in the same space as A, B, C and D.
Of course, if point is a vec4, with the last component as 1.0, then you can just do this:
dot(point, plane);
Where plane is a vec4 that contains A, B, C, and D. And that's your clip distance.
You also need to redeclare gl_ClipDistance with an explicit size in the shader stage that uses it. In GLSL 3.20+, gl_ClipDistance lives inside an interface block, so you have to redeclare that:
out gl_PerVertex
{
vec4 gl_Position;
float gl_ClipDistance[1];
};

How can this code retrieve a 2D vector from a cross-product of two 2D vectors?

I am in a lost. I have been trying to implement this code at:http://www.blackpawn.com/texts/pointinpoly/default.html
However, I don't know how is it possible that the cross-product present there between two 2D vectors can result also in a 2D vector. It does not make sense to me. That is also present in some examples of intersection between polygons and lines, in the fine book "Realtime Collision Detection" - where even scalar triples between 2D vectors appear in the codes (see page 189, for instance).
The issue is that, as far as I can think of it, the pseudo cross-product of two 2D vectors can only result in a scalar (v1.xv2.y-v1.yv2.x) or at most in a 3D vector if one adds two zeros, since that scalar represents the Z dimension. But how can it result in a 2D vector?
I am not the first one to ask this and, coincidently, when trying to use the same code example: Cross product of 2 2D vectors However, as can be easily seen, the answer, the original question when updated and the comments in that thread ended up being quite a mess, if I dare say so.
Does anyone know how should I get these 2D vectors from the cross-product of two 2D vectors? If code is to be provided, I can handle C#, JavaScript and some C++.
EDIT - here is a piece of the code in the book as I mentioned above:
int IntersectLineQuad(Point p, Point q, Point a, Point b, Point c, Point d, Point &r)
{
Vector pq = q - p;
Vector pa = a - p;
Vector pb = b - p;
Vector pc = c - p;
// Determine which triangle to test against by testing against diagonal first
Vector m = Cross(pc, pq);
float v = Dot(pa, m); // ScalarTriple(pq, pa, pc);
if (v >= 0.0f) {
// Test intersection against triangle abc
float u = -Dot(pb, m); // ScalarTriple(pq, pc, pb);
if (u < 0.0f) return 0;
float w = ScalarTriple(pq, pb, pa);
....
For the page you linked, it seems that they talk about a triangle in a 3d space:
Because the triangle can be oriented in any way in 3d-space, ...
Hence all the vectors they talk about are 3d vectors, and all the text and code makes perfect sense. Note that even for a 2d vectors everything also makes sense, if you consider a cross product to be a 3d vector pointing out of screen. And they mention it on the page too:
If you take the cross product of [B-A] and [p-A], you'll get a vector pointing out of the screen.
Their code is correct too, both for 2d and 3d cases:
function SameSide(p1,p2, a,b)
cp1 = CrossProduct(b-a, p1-a)
cp2 = CrossProduct(b-a, p2-a)
if DotProduct(cp1, cp2) >= 0 then return true
else return false
For 2d, both cp1 and cp2 are vectors pointing out of screen, and the (3d) dot product is exactly what you need to check; checking just the product of corresponding Z components is the same. If everything is 3d, this is also correct. (Though I would write simply return DotProduct(cp1, cp2) >= 0.)
For int IntersectLineQuad(), I can guess that the situation is the same: the Quad, whatever it is, is a 3d object, as well as Vector and Point in code. However, if you add more details about what is this function supposed to do, this will help.
In fact, it is obvious that any problem stated in 2d can be extended to 3d, and so any approach which is valid in 3d will also be valid for 2d case too, you just need to imagine a third axis pointing out of screen. So I think this is a valid (though confusing) technique to describe a 2d problem completely in 3d terms. You might yourself doing some extra work, because some values will always be zero in such an approach, but in turn the (almost) same code will work in a general 3d case too.

cv::remap (in opencv) and interp2 (matlab)

I am trying to look for an equivalent opencv function for interp2 and I understand that
cv::remap is a good way of doing this.
However, if I have the following:
f2 = interp2( x, y, f, x2, y2, 'bicubic' );
where x, y, x2 and y2 are all (say m x n) matrices, I am not sure how to use cv::remap for this.
How would I use remap for this? I know I have to convert it to a map ... but I'm unable to do so.
And,is there anything else that could do interp2 the way the matlab function does it?
In case you didn't find your answer yet, this is how you should use it.
remap(f,f2,x2,y2,CV_INTER_CUBIC);
The function remap supposes that you're working on exactly the grid where f is defined so no need to pass the x,y monotonic coordinates. I'm almost sure that the matrices cannot be CV_64F (double) so, take that into account.
interp2 is interpolator - if you get x,y and f values for some mesh it gives you the value f2 for x2 and y2.
remap - wraps your mesh by moving x and y coordinates acording to the deformation maps.
if you want interpolate regular mesh then use scaling (cv::resize for example).
If data is scattered then you can use Delaunay triangulation and then barycentric interpolation as variant or inverse distance weighting.

Function to generate some vectors of two values (x,y) of some forms

EDIT: I reformulate the question simply:
How do I generate in C++ or Python, random points (x,y) following: a circular distribution, a square distribution, and a triangular distribution.
This is a simple code for square for example:
def generateSquare(min, max, size):
data = []
for i in range(size):
x = randint(min, max)
y = randint(min, max)
data += [[x, y]]
return data
First of all, instead of storing your coordinates in a vector, you would be better off using std::pair or a custom class:
struct Point
{
int x;
int y;
};
Then you just need to have a way of generating random points, such as
Point randomPoint(Point const & min, Point const & max)
{
static std::mt19937 gen;
std::uniform_int_distribution<> distribX(min.x, max.x);
std::uniform_int_distribution<> distribY(min.y, max.y);
return Point{distribX(gen), distribY(gen)};
}
You can then use this generation function to fill your vector, for instance with generate_n:
unsigned int const nbPoints = 100;
std::vector<Point> points;
std::generate_n(back_inserter(points), nbPoints,
std::bind(randomPoint, Point{0, 0}, Point{1000, 1000}));
Note that this will generate random points, so you are not guaranteed to end up with a square, a triangle, etc. If you want to generate a could, you could either use a non-uniform distribution (if you know what distribution your coordinates follow) to generate your numbers, or use rejection sampling to discard points that are not in the area you want them to be.
Generating a triangle boils down to drawing three random points.
To generate a square, you can draw two points, corresponding to two opposite corners of the square.
And so on... I don't think there is a "universal" solution that would work for any shapes.
As supplement to Luc Touraille's post.
For a square find two random points and let these two points be the two furhest apart corners of the square.
For a triangle find three random points and let the triangle be triangle these three points make.
For a circle find a random point as a center for the circle and another random point, and let the distance between the two be the radius of the circle.
A more general approach could be to find the center point of the figures and let the parameters (scale, rotation, etc.) be found by further randomly generated numbers. (I guess a bit like Rook suggests).
Your problem is underspecified.
There is no such thing as a "circular distribution" or "triangular distribution".
You probably meant: a uniform distribution in the shape of a circle, rectangle, triangle.
There even is no uniquely specified triangle...
The key point is uniform.
E.g. a standard normal distribution in 2D may appear to be somewhat circular, but it is not exactly the shape of a circle.
There is no random generator that directly produces a circle with uniform density; at least not that I know of. The most common way is just to generate a square, and reject those points that you do not want to have.
E.g. generate (x,y) pairs on [0:1]x[0:1] and reject those with distance from .5,.5 larger than .5 - then you get the circle.
If you - as other users suggested - generate a radius and a distance, then the generated points will not be uniformly distributed on the circle.