POV-Ray : Newsgroups : povray.general : Minimum Distance Function : Re: Minimum Distance Function Server Time 8 Aug 2022 22:18:27 EDT (-0400)
 Re: Minimum Distance Function
 From: jceddy Date: 22 Jul 2022 09:35:00 Message:
```
{
"@context": "https://schema.org",
"@type": "DiscussionForumPosting",
"@id": "#web.62daa6ec6fb4e448864166f75d51d79c%40news.povray.org",
"dateCreated": "2022-07-22T13:35:00+00:00",
"datePublished": "2022-07-22T13:35:00+00:00",
"author": {
"@type": "Person",
"name": "jceddy"
}
}
> Been thinking about Blob, but haven't worked up the guts to attempt it yet. It
> seems like you should be able to come up with something you can feed to the root
> solver, but I'm still not clear on how to do it.

For Height Field, I implemented something similar to what I did for Mesh, where
I put all of the points in a kd-tree, then I look at all points with x- or z-
distance within the distance of the sample point to the nearest height field
vertex, plus one, triangulate the field mesh defined by those points, and check
for nearest point on any of those triangles. (Unless, that is, the y-coordinate
of the sample point is above the max-y or below the min-y of the height field,
in which case I just use the nearest vertex as the nearest point on the height
field). I haven't handled water-level yet.

Here is the code:

DBL HField::Proximity(Vector3d &pointOnObject, const Vector3d &samplePoint,
if (Data->kdTree == nullptr) {
return MAX_PROXIMITY_DISTANCE;
}

Vector3d transformedPoint = samplePoint;
Vector3d diff;
if (Trans != nullptr) {
MInvTransPoint(transformedPoint, transformedPoint, Trans);
}
DBL px = transformedPoint[X];
DBL py = transformedPoint[Y];
DBL pz = transformedPoint[Z];

Vector3d nearest = Data->kdTree->nearest_point(transformedPoint);

if (py < Data->min_y || py > Data->max_y) {
diff = nearest - transformedPoint;
}
else {
DBL dist = (nearest - transformedPoint).length();
DBL xmin = px - dist;
DBL zmin = pz - dist;
DBL xmax = px + dist;
DBL zmax = pz + dist;
int minX = max(0, int(xmin) - 1);
int maxX = min(Data->max_x, int(xmax) + 2);
int minZ = max(0, int(zmin) - 1);
int maxZ = min(Data->max_z, int(zmax) + 2);

dist = MAX_PROXIMITY_DISTANCE;
for (int z = minZ; z < maxZ - 1; z++)
{
for (int x = minX; x < maxX - 1; x++)
{
Vector3d p1(x, Data->Map[z][x], z);
Vector3d p2(x + 1, Data->Map[z][x + 1], z);
Vector3d p3(x + 1, Data->Map[z + 1][x + 1], z + 1);
Vector3d p4(x, Data->Map[z + 1][x], z + 1);

Vector3d trianglePt;
DBL test = NearestOnTriangle(trianglePt, transformedPoint, p1, p2, p3);
if (test < dist) {
dist = test;
nearest[X] = trianglePt[X];
nearest[Y] = trianglePt[Y];
nearest[Z] = trianglePt[Z];
}

test = NearestOnTriangle(trianglePt, transformedPoint, p1, p3, p4);
if (test < dist) {
dist = test;
nearest[X] = trianglePt[X];
nearest[Y] = trianglePt[Y];
nearest[Z] = trianglePt[Z];
}
}
}

diff = nearest - transformedPoint;
}

if (Trans != nullptr) {
MTransDirection(diff, diff, Trans);
}

pointOnObject = samplePoint + diff;
return diff.length();
}

I am getting really high max gradient values (resulting in isosurface holes)
around the highest and lowest points in the field, and I'm not clear on whether
that is due to a problem in the code, or maybe like due to the orientation of
the triangles relative to the camera ray there or something, so thought I would
ask if anyone could take a look at this and let me know if they see any glaring
issue.

Cheers,
Joe
```