Prod.: Engine, ver.: 6, ID: 60000202, HowTo : How to calculate the point that a user clicks on a polyface in 3D

HowTo : How to calculate the point that a user clicks on a polyface in 3D

Article60000202
TypeHowTo
ProductEngine
Version6
Date Added7/17/2007
Submitted byChanios Peter
Keywords

Subject

How to calculate the point that a user clicks on a polyface in 3D

Summary

How to calculate the point that a user clicks on a polyface in 3D.

Solution

In the following code sample we ask the user to click a point.We check if the user clicked a polyface. From this point we calculate a Line that goes from the user's "eye" and inside. We calculate the intersection points of this line and all the faces of the found polyface. Then we exclude all the points that do not belong to the face and we select the point that is closer to the user's "eye".

Important Functions Used : Intersection3DSegmentPlane,PointInTriangle, CalculateExtrution  can be found in VectorDraw.Geometry.Globals.

private void button4_Click(object sender, EventArgs e)
{
vdDocument doc = vdFramedControl1.BaseControl.ActiveDocument;
gPoint userpt = null;
//Get a point from the user
VectorDraw.Actions.StatusCode s= doc.ActionUtility.getUserPointDCS(out userpt);
if (s == VectorDraw.Actions.StatusCode.Success)
{
//Find the polyface the user clicked.
gPoint tmppt = doc.View2PixelMatrix.Transform(userpt);
Point screenpt = new Point((int)tmppt.x, (int)tmppt.y);
//This function it is recommended not to go to the Mouse Down event(it might slow down your application)
//It is recommended to create a button function to do this like this one.
vdEntities ents = doc.Select3d(screenpt, doc.GlobalRenderProperties.PickSize);
if (ents.Count != 0)
{
vdPolyface polyface = ents[0] as vdPolyface;
if (polyface != null)
{
//Calculate the biggest z value of the polyface.
double val = 0.0;
foreach (gPoint var in polyface.VertexList)
{
if (val < var.z) val = var.z;
}
//Calculate the line that starts from the point that the user clicked and goes "inside the screen" to intersect the face.
gPoint world = doc.View2WorldMatrix.Transform(userpt);
gPoint linept1 = world - (val * 10.0) * doc.ActiveLayOut.ViewDir;
gPoint linept2 = world + (val*10.0)*doc.ActiveLayOut.ViewDir;
gPoints FoundPoints = new gPoints();
int count = 1;
foreach (int var in polyface.FaceList)
{
count++;
if (count % 5 == 0)
{
//4 points of the face.
gPoint pt1 = polyface.VertexList[polyface.FaceList[count - 5] - 1];
gPoint pt2 = polyface.VertexList[polyface.FaceList[count - 4] - 1];
gPoint pt3 = polyface.VertexList[polyface.FaceList[count - 3] - 1];
gPoint pt4 = polyface.VertexList[polyface.FaceList[count - 2] - 1];
//Calculate the perpedicular vector of the plane of the face.
Vector v = new Vector();
v.CalculateExtrution(pt1, pt2,pt3);
//Calculate the intersection point of the plane with the above calculated line
gPoint ret1 = new gPoint();
int j = VectorDraw.Geometry.Globals.Intersection3DSegmentPlane(linept1, linept2, v, pt1, out ret1);
if (j != 0)
{
bool triangle1 = VectorDraw.Geometry.Globals.PointInTriangle(doc.World2ViewMatrix.Transform (ret1),doc.World2ViewMatrix.Transform ( pt1), doc.World2ViewMatrix.Transform (pt2), doc.World2ViewMatrix.Transform (pt3));
bool triangle2 = VectorDraw.Geometry.Globals.PointInTriangle(doc.World2ViewMatrix.Transform (ret1),doc.World2ViewMatrix.Transform ( pt1),doc.World2ViewMatrix.Transform ( pt3), doc.World2ViewMatrix.Transform (pt4));
if (triangle1 || triangle2) //If the point belongs to any of the triangles then belongs to the face.
{
//Add the found point to this list.
FoundPoints.Add(ret1);
}
}
}
}
//Debug Add a vdPoint for each point found.
foreach (gPoint var in FoundPoints)
{
vdPoint vdpt = new vdPoint();
vdpt.SetUnRegisterDocument(doc);
vdpt.setDocumentDefaults();
vdpt.PenColor.ColorIndex = 2;
vdpt.InsertionPoint = var;
doc.ActiveLayOut.Entities.AddItem(vdpt);
vdpt.Invalidate();
}
//This is for debug purposes we will add the calculated line and the Found Point.
vdLine line = new vdLine(linept1, linept2);
line.SetUnRegisterDocument(doc);
line.setDocumentDefaults();
line.PenColor.ColorIndex = 0;
doc.ActiveLayOut.Entities.AddItem(line);
line.Invalidate();

//Now we will choose the point that has the less distance from linept2
int index = 0;
int indexFound = 0;
double dist = linept1.Distance3D(linept2); //We start from the biggest distance
foreach (gPoint var in FoundPoints)
{
double dist1 = var.Distance3D(linept2);
if (dist1 < dist)
{
indexFound = index;
dist = dist1;
}
index++;
}
//Add the Found point with different color.
vdPoint vdpt1 = new vdPoint();
vdpt1.SetUnRegisterDocument(doc);
vdpt1.setDocumentDefaults();
vdpt1.PenColor.ColorIndex = 3;
vdpt1.InsertionPoint = FoundPoints[indexFound];
doc.ActiveLayOut.Entities.AddItem(vdpt1);
vdpt1.Invalidate();
}
}
}
}