Missing Triangles When Creating Surface

Missing Triangles When Creating Surface

soonhui
Advisor Advisor
583 Views
5 Replies
Message 1 of 6

Missing Triangles When Creating Surface

soonhui
Advisor
Advisor

When creating a TIN surface from a PolyFaceMesh using AddFromPolyFaces, not all triangles appear in the final surface, even though they are correctly defined in the mesh.

 

image1.png

 

Missing triangles

 

image1.png

 

Expected area

 

The issue can be reproduced via the following code:

 

[CommandMethod("Test")]
public void Test()
{
	var doc = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument;
	var db = doc.Database;
	var civilDoc = CivilDocument.GetCivilDocument(db);
 
	using (doc.LockDocument())
	using (var tr = db.TransactionManager.StartTransaction())
	{
    	var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
    	var btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
 
    	var mesh = new PolyFaceMesh();
    	mesh.SetDatabaseDefaults();
    	btr.AppendEntity(mesh);
    	tr.AddNewlyCreatedDBObject(mesh, true);
 
    	var coords = new[]
    	{
        	new Point3d(281369.6831, 711012.3484, 32600),
        	new Point3d(554192.1153, 583139.5499, 32600),
        	new Point3d(447598.0605, 299186.0469, 32600),
        	new Point3d(360358.5154, 113734.1993, 32600),
        	new Point3d(177125.9921, 199246.3057, 32600),
        	new Point3d(159658.2854, 163972.7882, 32600),
        	new Point3d(58598.3385, 224746.4580, 32600),
    	};
 
    	foreach (var pt in coords)
    	{
        	var vtx = new PolyFaceMeshVertex(pt);
        	mesh.AppendVertex(vtx);
        	tr.AddNewlyCreatedDBObject(vtx, true);
    	}
 
    	var tris = new[]
    	{
        	new[] { 0, 1, 2 },
        	new[] { 0, 2, 3 },
        	new[] { 0, 3, 4 },
        	new[] { 0, 4, 5 },
        	new[] { 0, 5, 6 },
    	};
 
    	foreach (var t in tris)
    	{
        	var face = new FaceRecord((short)(t[0] + 1), (short)(t[1] + 1), (short)(t[2] + 1), 0);
        	mesh.AppendFaceRecord(face);
        	tr.AddNewlyCreatedDBObject(face, true);
    	}
 
    	var surfId = TinSurface.Create(db, "surfaceName");
    	var surface = (TinSurface)tr.GetObject(surfId, OpenMode.ForWrite);
        surface.DrawingObjectsDefinition.AddFromPolyFaces(new ObjectIdCollection(new[] { mesh.ObjectId }), true, "desc");
 
    	var toDelete = surface.GetEdges().Where(e => !e.IsLocked).ToList();
    	if (toDelete.Count > 0) surface.DeleteLines(toDelete);
 
    	mesh.Erase();
    	surface.Rebuild();
 
    	tr.Commit();
	}
}

 

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software. Read more here


I also setup Civil WHIZ in order to share what I learnt about Civil 3D
0 Likes
584 Views
5 Replies
Replies (5)
Message 2 of 6

CodeDing
Mentor
Mentor

@soonhui ,

 

Looks like it has to do with how your faces are created. I avoided having them all start/end at the same vertex. this worked for me:

var tris = new[]
{
    new[] { 0, 1, 2 },
    new[] { 2, 0, 3 },
    new[] { 3, 0, 4 },
    new[] { 4, 0, 5 },
    new[] { 5, 0, 6 },
};

Also, I updated your 0 to be a 1 here (vertex 3):

var face = new FaceRecord((short)(t[0] + 1), (short)(t[1] + 1), (short)(t[2] + 1), 1);

 

image.png

 

Best,

~DD

0 Likes
Message 3 of 6

soonhui
Advisor
Advisor

@CodeDing , I understand your workaround. But the main issue is, why Civil 3D can't work properly with my input data? This seems to me like a bug. 

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software. Read more here


I also setup Civil WHIZ in order to share what I learnt about Civil 3D
0 Likes
Message 4 of 6

soonhui
Advisor
Advisor

One thing I would like to stress to the Civil 3D team is that, the API should work well regardless of how I arrange my face. Alas this is not happening and which is why I said this is a bug. 

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software. Read more here


I also setup Civil WHIZ in order to share what I learnt about Civil 3D
0 Likes
Message 5 of 6

soonhui
Advisor
Advisor

@CodeDing , your workaround only works in that contrived case. There's still some missing triangles in the following test case (modified from test above by adding an extra triangle). Note that the start vertex and end vertex are all unique as you suggested. 

 

Another incorrect behavior is that this issue only happens when the coordinates are scaled down (eg. divided by 1000). The surface is intact if the coordinates are not scaled down.

 

 var coords = new[]
                {
                    new Point3d(281375, 711025, 32599.999999999996),
                    new Point3d(554175, 583125, 32599.999999999996),
                    new Point3d(447574.xxx-xxxxxxxx, 299175, 32599.999999999996),
                    new Point3d(394325, 182775, 32599.999999999996),
                    new Point3d(360375, 113725, 32599.999999999996),
                    new Point3d(177125, 199225, 32599.999999999996),
                    new Point3d(159675, 163975, 32599.999999999996),
                    new Point3d(58575, 224725, 32599.999999999996),
                };

                foreach (var pt in coords)
                {
                    var vtx = new PolyFaceMeshVertex(new Point3d(pt.X/1000, pt.Y/1000, pt.Z/1000));
                    mesh.AppendVertex(vtx);
                    tr.AddNewlyCreatedDBObject(vtx, true);
                }

                var tris = new[]
                {
                    new[] { 0, 1, 2 },
                    new[] { 2, 3, 0 },
                    new[] { 4, 0, 3 },
                    new[] { 5, 0, 4 },
                    new[] { 6, 0, 5 },
                    new[] { 7, 0, 6 },
                };

 

Here’s what the surface looks like using the inputs provided above.

 

image1.png

 

If we modify the FaceRecord to start from index 1 instead of 0 (as in your workaround), the result becomes even less correct, with more triangles missing.

 

image2.png

 

 

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software. Read more here


I also setup Civil WHIZ in order to share what I learnt about Civil 3D
0 Likes
Message 6 of 6

hippe013
Advisor
Advisor

The documentation states:

The appended vertex must be explicitly closed by the calling application after the AppendVertex() call returns.

The appended FaceRecord must be explicitly closed by the calling application after the AppendFaceRecord() call returns.

 

Would you agree that your new PolyFaceMeshVertex and your new FaceRecord should be wrapped in a using statement or at least explicitly disposed? 

 

 

0 Likes