This is just an educated guess, but the artifacts in your visualization of the curvature values reminded me of Moiré patterns. The images in the Wikipedia article don't show circle patterns like the ones you are observing, but I have seen similar patterns before when I tried to visualize highly oscillating functions. (Edit: The function you are visualizing, i.e. the curvature, is likely not oscillating quickly. However, the following example still illustrates that it may not only be the discretization or mesh generation algorithm that is problematic, but also the computation of the curvature.)
For example, if you try to visualize the function $f(x,y) = |\cos((x^2+y^2)^2)|$ for $x$ and $y$ ranging from $-3.3$ to $3.3$ on a grid of $256\times 256$ pixels, what you get is the following image:
The Moiré patterns appear in this image since the function $f$ is only evaluated at a single point (x,y) for every pixel, although each pixel covers not just a single point but an area. A better visualization of the function $f$ would involve integrating over the corresponding area for each pixel, which would result in a uniform gray color near the image boundaries reduces the Moiré patterns.
My guess is that there is something similar happening in your situation. As for solving your problem, this essentially means that the curvature is computed in an erroneous way if the discretization is too coarse. So you could either try to improve the algorithm that is used for the computation of the curvature or simply use a finer discretization. Unless, of course, if the rings really are a feature of your surface, in which case they will not disappear as lightxbulb pointed out.
In case you are interested, I have attached the C++ code that I used to generate the above image. Note that if you increase X
and Y
while keeping lX
and lY
constant, the discretization is refined and the Moiré patterns will disappear.
#include <fstream>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
void WriteGrayscalePPM(const std::string& file, const std::vector<unsigned char>& values, const unsigned int X) {
const unsigned int Y = values.size ( ) / X;
std::ofstream image(file.c_str(), ios::out | ios::binary);
image << "P6\n" << X << ' ' << Y << "\n255\n";
for (unsigned int i=0; i<X*Y; i++) {
unsigned char color[3] = {values[i], values[i], values[i]};
image.write((const char*)color, 3*sizeof(char));
}
}
int main(int argc, char **argv) {
const int X = 256;
const int Y = 256;
const double lX = 3.3;
const double lY = 3.3;
std::vector<unsigned char> values(X*Y, 0);
for (int y=0; y<Y; y++) for (int x=0; x<X; x++) {
double xd = lX / (X/2) * (x - X/2);
double yd = lY / (Y/2) * (y - Y/2);
double d = sqrt(xd*xd + yd*yd);
values[x + y*X] = 255*abs(cos(d*d*d*d));
}
WriteGrayscalePPM("moire.ppm", values, X);
return 0;
}