2

Hello I have a problem which I believe is very difficult to solve, I was searching everywhere for solution but I didn't find anything.

I want to draw profiles from list of points.

My problem is:

  1. I have a list of Points3D from text file, they arent in any order, just like random points. Of course I added them to List. I draw those points in 3D space using small 3D Ellipses. So far so good.
  2. Now I want to draw a 3D spline going through all the points from list. So i created class Spline3D which is using cubic interpolation to determine positions of points of curve between given points from text file. In my spline I calculate say like 400 new points then I am drawing small 3D Cylinders between each pair of points: point i and point i+1 have small cylinder betwen them + the cylinders are rotated properly so everything is looking like real spline (in theory).

The main problem is that points are unordered so if I am just doing that I get spline like this:

http://img5.imageshack.us/img5/4659/2b61.jpg

the raw points draw in space look like this:

http://img194.imageshack.us/img194/9016/hv8e.jpg

http://img5.imageshack.us/img5/659/nsz1.jpg

So i figure out that I have two solutions

  1. Put points in some sort of order, then add them to Spline3D and calculate spline.

  2. Calculate spline in some other way, which probably lead to order points in some way, so basically it still lead me to 1.

So I tried some kinds of reordering methods.

1. a) Nearest neighbor of point

int firstIndex = (new Random().Next(pointsCopy.Count));//0;//pointsCopy.Count / 2;//(new Random().Next(pointsCopy.Count));
NPoint3D point = pointsCopy[firstIndex];
pointsCopy.Remove(point);

spline3D.addPoint(point.ToPoint3D());

NPoint3D closestPoint = new NPoint3D();

double distance;
double nDistance;

Point3D secondPoint = new Point3D();
bool isSecondPoint = true;

while (pointsCopy.Count != 0)
{
    distance = double.MaxValue;

    for (int i = 0; i < pointsCopy.Count; i++)
    {
        nDistance = point.distanceToPoint(pointsCopy[i]);
        if (nDistance < distance)
        {
            distance = nDistance;
            closestPoint = pointsCopy[i];
        }
    }
    if (isSecondPoint)
    {
        isSecondPoint = false;
        secondPoint = closestPoint.ToPoint3D();
    }

    spline3D.addPoint(closestPoint.ToPoint3D());
    point = closestPoint;
    pointsCopy.Remove(closestPoint);
}
spline3D.addPoint(points[firstIndex].ToPoint3D()); //first point is also last point

This was my first idea, I thought that this will became ultimate solution to my problem. I choose randomly one point from list of points and this point became first point to spline. Then I find the closest point to this previous point I add him to spline and remove from list and so on...

http://img18.imageshack.us/img18/3650/mik0.jpg

http://img706.imageshack.us/img706/3834/u97b.jpg

Sadly sometimes (especially near edges of my profile) point down is closer then point near, so spline became there crooked.

2. b) TSP

    distanceMatrix = new TSP.DistanceMatrix(pointsCopy, NPoint3D.distanceBetweenTwoPoints);
int[] indexes = TSP.Algorithms.TSPgreedySearch(distanceMatrix);
for (int i = 0; i < indexes.Length; i++)
    spline3D.addPoint(pointsCopy[indexes[i]].ToPoint3D());
spline3D.addPoint(pointsCopy[indexes[0]].ToPoint3D());

Basically I use traveling salesman problem algorithm to determine shortest spline (shortest path) through all the points. Sadly this problem is NP-Hard, so to get good performance I use some heuristics.

http://img198.imageshack.us/img198/714/xiqy.jpg

http://img839.imageshack.us/img839/9530/exnu.jpg

Spline looks better than in 1.a but still it isn't enough.

3. c) Some weird methods using two splines

Some of my friends told me that I should split profile in two parts (upper-part and lower-part) and then calculate and draw two splines. Sadly I dont know how to do that, I mean I don't know how to determine if point should be in upper-part or lower-part. Please help me.

So how could I solve this problem? Any ideas?

OneFineDay
  • 9,004
  • 3
  • 26
  • 37
Pawel Troka
  • 853
  • 2
  • 12
  • 33

1 Answers1

1

It sounds like you're looking for the Concave Hull of the data set.

Unfortunately, I don't know of any pre-canned algorithms, but the link references a paper that another developer was starting from, as well as some sample code, so maybe that'll help you in the right direction.

Community
  • 1
  • 1
Andrew Coonce
  • 1,557
  • 11
  • 19
  • It's good, but I dont know how to applied it to 3D. How should I calculate the angle? – Pawel Troka Aug 22 '13 at 19:08
  • @PandaWoll: Theoretically, the angle between two vectors Va and Vb would be dot(Va,Vb)/(||Va|| * ||Vb||). Whether that's useful here or not... sorry, I'm just not certain I know how to take it further. – Andrew Coonce Aug 22 '13 at 20:11
  • 1
    @PandaWoll: To be completely honest, you're trying to take a 3D point cloud and turn it into a mesh from only a handful of cross-sectional areas. If there's a way to do this, it's almost certainly theoretically complex and NP-hard. I would worry about finding *any* solution first, then worry about efficiency later. – Andrew Coonce Aug 22 '13 at 20:16