How to smoothly interpolate color along a Java2D path? - vector-graphics

I'm from a 3D rendering background where this is trivial to do, but I can't find how to do this in Java2D:
Say I have points A, B and colors cA, cB.
The points are joined together by a quadTo() command and stroked. I want the colors to smoothly interpolate between each point. i.e. point A is color cA, point B is color cB, and the color of the line between A and B linearly interpolates between cA and cB.
I've tried stroking with a gradient fill but for my purposes it is far too slow, and also produces inaccurate results since I am actually joining up hundreds of these curve segments into continuous paths (using GeneralPath).
Is good 'ole point to point linear color interpolation not supported in Java2D?

The answer is: you can't do it. Java2D doesn't support this operation.

Related

How to do a "color-by-number" plot in Octave

I have two parameters or coordinates x and y, and a quantity E(x,y,p) which is a function of those two parameters, but also depends on a state matrix p. I have a few discrete options for the state p - say, p1, p2, p3... - and for every pair (x,y) I run some calculations to find which of the possible states p minimizes E(x,y,p).
Once I have this information, I would like to make a 2D plot in which the region surrounding the point (x,y) is colored e.g. green if state p1 minimized E, blue if state p2 minimized E, etc.
There's probably a simple way to do this that I just haven't figured out yet. I didn't see a good way to do it among the specialized plots, but I was having trouble understanding a few that may have been relevant, e.g. pcolor and patch. Any advice on how to do this?
The best I've thought of is using surf with the z-value used to control the color, and then doing a top-down view of the 3D plot to get the 2D plot I want. That seems like a clunky way of doing things, though.
I was able to do the job with pcolor after all. I defined Emin(x,y)=E(x,y,p) for the p that minimized E(x,y,p) and then called pcolor(Emin). I was able to add ticks on the axes by calling pcolor(xvec,yvec,Emin) where xvec is an array of the different values of x used, etc.
pcolor works by coloring in cells based on the vertices defined by xvec and yvec, or if those are not given, based on the indices of Emin, this doesn't center the cells on the coordinates corresponding to that value. For example, if I calculate Emin(1,2)=5 and call pcolor(Emin) then the cell with the color corresponding to 5 will have its corner at coordinates (1,2). I can fix this by shifting xvec and yvec by half the width of a cell. For cells of unit width, for example, this would be xvec = xvec - 0.5. The last row and column of Emin don't show up, but I can fix this by adding a dummy row and column to it.
In case it's relevant, I was only using linearly spaced xvec and yvec, so if there could be complications I avoided with other spacings.
Hopefully this makes some sense to anyone else who has trouble reading the documentation for pcolor that I had found.

Coloring Rgl 3d mesh faces

I'd like to color faces on an triangular RGL mesh based on proximity to a vertex.
The thing is, it seems that a lot of the times that the vertices are associated with faces that are very far from the actual vertex location itself, which creates a problem when I want to color faces around one vertex; the faces end up being very far from where the barycenter actually is.
What I'm doing right now is this:
Compute the barycenter of all the faces in the mesh.
Use the FAR package to compute the closest n barycenters to the desired point. Keep those indices.
Based on the indices gathered, color those faces a certain color. The rest of the faces would be colored white.
colors=rep('white',num_faces)
colors[colored_faces]='red'
mesh$material=list(color=colors)
Then I would plot the mesh: plot3d(mesh)
The thing is, I'm getting very odd coloring right now, is there any established way to color faces that close to a certain coordinate/vertex?
This is what the mesh currently looks like, with the red as the 'colored' faces, and the blue as the points that I would like there to be a colored face near.
Mesh
Update: Seeing this, my question has now been modified to:
How can I find the closest face to a given point? It still isn't clear to me, since the face barycenters are sometimes misleading, and don't represent actual distance to a given vertex.
Update 2:
I've added example code and a file here: Files and code
Basically the code finds the nearest faces to a given vertex of the same 3d mesh with the nearest neighbor algorithm, and then we color those faces in our color vector (remembering to color the colors 4 times):
Except, when we run this algorithm, we only color one side of the shape: like so:
Odd
How can I make the coloring a bit more symmetric?
Update 3: This problem has been resolved! Please look to the unreleased version of rgl on Rforge for the newest version of rgl that allows for coloring of faces, vertices, and edges.
Update 4: Here is the new image by coloring the closest vertices (to show that the new rgl package works wonders):
Better Sink
Your code to compute the centroid is incorrect. You have
#Function for computing the barycenter/centroid of a face.
compute_face_centroid=function(vertices,face){
vertex=vertices[,face][-4,]
centroid=apply(X=vertex,MARGIN = 1,FUN = mean)
return(centroid)
}
This just removes the 4th row of the vertices array, which is the wrong way to convert homogeneous coordinates to Euclidean coordinates. You really need to divide the other rows by the 4th one. You can do this using the rgl function asEuclidean:
#Function for computing the barycenter/centroid of a face.
compute_face_centroid=function(vertices,face){
vertex <- asEuclidean(t(vertices[,face]))
apply(vertex, MARGIN = 2, FUN = mean)
}
There may also be other issues in your code, I haven't traced through everything yet.
BTW, the unreleased test version of rgl changes the way colours are handled in meshes, hopefully making that part of your code simpler. You can get it from R-forge.r-project.org if you want to try it. You can now specify colours by vertex or by face.
Edited to add:
Okay, I've taken a closer look now. I think your code was actually working. The compute_face_centroid should be corrected, but since your example always has value 1 for the final component, deleting it is okay.
The reason you got colouring different from what you expected is just that the triangles making up your mesh really vary in shape. If you plot your image as a wireframe you'll see this:
wire3d(file)
The centroids of those long thin triangles are quite far from your selected point.

Fit surface to 3 to 100 points where z values are 3D

I found myself in quite a big problem. I am average in math and I need to solve something, which is not very covered on the internet.
My problem: I have 2D space defined by X and Y. This space is just a drawing space. I want to assign to particular Xs,Ys a color with RGB values.
So let says I have 4 points with defined position in XY and color in Z:
[0,0, [255,0,0]]
[0,10, [0,255,0]]
[10,10,[0,0,255]]
[5,5, [0,0,0]]
and my drawing space is xy: 15x15.
And I want to distribute the colors to all empty points
For me its quite a delicate problem, because Z axis is basicly 3D space by itself.
My whole intention is to create a color map in which points 1,2,3,4 have between them smooth transition.
I am able to solve this in 1D where the transition is between 2 points. But I need to create 2D color map in XY drawing space based on fitted surface to these 4 points, which kind of depend both on the space of 3D-RGB and distance between them in XY drawing space.
Thanks in advance for help
You do not show any algorithm or code, so I will just explain a high-level algorithm. If you need more details or code or mathematical formulae, show more of your own work then ask. You do not explain just what you mean by "smooth transition"--there are multiple meanings. This will result in continuous shading but may not be smooth enough for your purposes.
First, given your points in the rectangular drawing space, find the Voronoi diagram for those points. This divides the drawing space into convex polygons, each polygon around one of your points.
For each vertex in the Voronoi diagram, figure which points are closest to the vertex--there will usually be just three of your points but there could be more. Then at that vertex point, assign the color that is the average of the RGB values of the nearby given points. That is, average the R values and the G values and the B values separately.
For any point on a Voronoi polygon edge, its color is the weighted average of the two colors at the endpoints. I.e. If the point is one-third of the distance from one end, its RGB value is one-third of the distance from the values at the endpoints.
Finally, for any point inside a Voronoi polygon, calculate the ray from the point that defined that polygon (the "center point") through the current point you are looking at. Find where that ray intersects the polygon. The RGB value is then the weighted average of the values of the center point and the polygon-intersection point.
The hardest part of all that is finding the Voronoi diagram. Fortune's algorithm can do this in a reasonable time. You can probably find a library to do that for you in your chosen programming language.
Another algorithm is to start with a triangulation of your given points and the corners of the drawing region. Then the color of any point in a triangle is the weighted average of the colors of the vertices. This will be automatically consistent for points on the vertices or edges of the triangles, so this is probably simpler than my previous algorithm. The difficulty here is finding a triangulation (any will do).

Domain coloring (color wheel) plots of complex functions in Octave (Matlab)

I understand that domain or color wheel plotting is typical for complex functions.
Incredibly, I can't find a million + returns on a web search to easily allow me to reproduce some piece of art as this one in Wikipedia:
There is this online resource that reproduces plots with zeros in black - not bad at all... However, I'd like to ask for some simple annotated code in Octave to produce color plots of functions of complex numbers.
Here is an example:
I see here code to plot a complex function. However, it uses a different technique with the height representing the Re part of the image of the function, and the color representing the imaginary part:
Peter Kovesi has some fantastic color maps. He provides a MATLAB function, called colorcet, that we can use here to get the cyclic color map we need to represent the phase. Download this function before running the code below.
Let's start with creating a complex-valued test function f, where the magnitude increases from the center, and the phase is equal to the angle around the center. Much like the example you show:
% A test function
[xx,yy] = meshgrid(-128:128,-128:128);
z = xx + yy*1i;
f = z;
Next, we'll get its phase, convert it into an index into the colorcet C2 color map (which is cyclic), and finally reshape that back into the original function's shape. out here has 3 dimensions, the first two are the original dimensions, and the last one is RGB. imshow shows such a 3D matrix as a color image.
% Create a color image according to phase
cm = colorcet('C2');
phase = floor((angle(f) + pi) * ((size(cm,1)-1e-6) / (2*pi))) + 1;
out = cm(phase,:);
out = reshape(out,[size(f),3]);
The last part is to modulate the intensity of these colors using the magnitude of f. To make the discontinuities at powers of two, we take the base 2 logarithm, apply the modulo operation, and compute the power of two again. A simple multiplication with out decreases the intensity of the color where necessary:
% Compute the intensity, with discontinuities for |f|=2^n
magnitude = 0.5 * 2.^mod(log2(abs(f)),1);
out = out .* magnitude;
That last multiplication works in Octave and in the later versions of MATLAB. For older versions of MATLAB you need to use bsxfun instead:
out = bsxfun(#times,out,magnitude);
Finally, display using imshow:
% Display
imshow(out)
Note that the colors here are more muted than in your example. The colorcet color maps are perceptually uniform. That means that the same change in angle leads to the same perceptual change in color. In the example you posted, for example yellow is a very narrow, bright band. Such a band leads to false highlighting of certain features in the function, which might not be relevant at all. Perceptually uniform color maps are very important for proper interpretation of the data. Note also that this particular color map has easily-named colors (purple, blue, green, yellow) in the four cardinal directions. A purely real value is green (positive) or purple (negative), and a purely imaginary value is blue (positive) or yellow (negative).
There is also a great online tool made by Juan Carlos Ponce Campuzano for color wheel plotting.
In my experience it is much easier to use than the Octave solution. The downside is that you cannot use perceptually uniform coloring.

why do I not find a LAB color cube?

I use the R colorspace package to convert a three-dimensional point into a LAB color. The LAB color is defined with three coordinates, the first one ranges from 0 to 100 and the two other ones range from -100 to 100.
But searching with Google I do not find a cuboidal representation of the LAB color space. Why ?
Short answer
The LAB color space, a.k.a. gamut, contain colors that are impossible to reproduce in nature or on a screen (according to this page).
Elaboration on converting RGB to LAB
I guess the reason you ask is that you want to make some kind of printed material and want to be sure the colors turn out right. I am merely an enthusiastic amateur in this field, but think this paragraph from the wikipedia article on lab color space explains some of the complications.
There are no simple formulas for conversion between RGB or CMYK values
and L*a*b*, because the RGB and CMYK color models are device
dependent. The RGB or CMYK values first need to be transformed to a
specific absolute color space, such as sRGB or Adobe RGB. This
adjustment will be device dependent, but the resulting data from the
transform will be device independent, allowing data to be transformed
to the CIE 1931 color space and then transformed into L*a*b*.
That is, in order to create a lab color cube, you must first find the transformation from your monitor specific color space into absolute color space. This is surprisingly difficult since the mapping is not linear or on any other simple form. The transformation is not likely to be perfect either since the RGB and LAB spaces do not span the same subspace (speculating here). I once talked to a printmaker about this and he said altough the human eye only has 4 types of color receptors (RGB + light intensity) you need about 17 color components on generate the full spectrum of visible colors on paper. Both RGB and LAB compromises on that, optimized for different purposes.
Bottom line
You can calibrate your screen to set up the transformation needed to convert the RGB of the screen to the LAB colors of human eyes, and then go on to make a color cube. However, it will only apply to your very monitor and not be perfect. You are best off test printing different color profiles and choose the one you like best.
Because there is no such thing. The CIELAB colour space has a Cartesian representation (of infinite size), but the (finite) gamut that we can perceive is not cubic, it has a complicated shape. Varying the two coordinates a* and b* independently in a pre-defined range may seem convenient, but this is fundamentally not the way human perception works.

Resources