在三维空间中工作(.NET)

大多数图形由三维(3D)对象的二维(2D)视图组成。虽然这种绘图方法在建筑和工程界广泛使用,但它是有限的:图纸是3D对象的2D表示,必须进行视觉解释。此外,由于视图是独立创建的,因此出现错误和歧义的可能性更大。因此,您可能希望创建真正的3D模型,而不是2D表示。您可以使用AutoCAD绘图工具创建详细、逼真的三维对象,并以各种方式对其进行操作。

本节中的主题

  • 指定三维坐标(.NET)
  • 定义用户坐标系(.NET)
  • 转换坐标(.NET)
  • 创建3D对象(.NET)
  • 在3D中编辑(.NET)
  • 编辑三维实体(.NET)

指定三维坐标(.NET)

输入三维世界坐标系(WCS)坐标与输入二维WCS坐标类似。除了指定X和Y值外,还可以指定Z值。2D坐标由 Point2d 对象表示,而您使用 Point3d 对象表示3D坐标。AutoCAD .NET API中的大多数特性和方法都使用三维坐标。

定义和查询二维和三维多段线的坐标

本示例创建两条多段线,每条多段线有三个坐标。第一个图形是二维图形,第二个图形是三维图形。请注意,包含顶点的数组的长度将扩展,以在创建三维对象时包括Z坐标。该示例最后查询多段线的坐标并在消息框中显示坐标。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
[CommandMethod("Polyline_2D_3D")]
public static void Polyline_2D_3D()
{
// Get the current document and database, and start a transaction
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Open the Block table record for read
BlockTable acBlkTbl;
acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
OpenMode.ForRead) as BlockTable;

// Open the Block table record Model space for write
BlockTableRecord acBlkTblRec;
acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],
OpenMode.ForWrite) as BlockTableRecord;

// Create a polyline with two segments (3 points)
using (Polyline acPoly = new Polyline())
{
acPoly.AddVertexAt(0, new Point2d(1, 1), 0, 0, 0);
acPoly.AddVertexAt(1, new Point2d(1, 2), 0, 0, 0);
acPoly.AddVertexAt(2, new Point2d(2, 2), 0, 0, 0);
acPoly.ColorIndex = 1;

// Add the new object to the block table record and the transaction
acBlkTblRec.AppendEntity(acPoly);
acTrans.AddNewlyCreatedDBObject(acPoly, true);


// Create a 3D polyline with two segments (3 points)
using (Polyline3d acPoly3d = new Polyline3d())
{
acPoly3d.ColorIndex = 5;

// Add the new object to the block table record and the transaction
acBlkTblRec.AppendEntity(acPoly3d);
acTrans.AddNewlyCreatedDBObject(acPoly3d, true);

// Before adding vertexes, the polyline must be in the drawing
Point3dCollection acPts3dPoly = new Point3dCollection();
acPts3dPoly.Add(new Point3d(1, 1, 0));
acPts3dPoly.Add(new Point3d(2, 1, 0));
acPts3dPoly.Add(new Point3d(2, 2, 0));

foreach (Point3d acPt3d in acPts3dPoly)
{
using (PolylineVertex3d acPolVer3d = new PolylineVertex3d(acPt3d))
{
acPoly3d.AppendVertex(acPolVer3d);
acTrans.AddNewlyCreatedDBObject(acPolVer3d, true);
}
}

// Get the coordinates of the lightweight polyline
Point2dCollection acPts2d = new Point2dCollection();
for (int nCnt = 0; nCnt < acPoly.NumberOfVertices; nCnt++)
{
acPts2d.Add(acPoly.GetPoint2dAt(nCnt));
}

// Get the coordinates of the 3D polyline
Point3dCollection acPts3d = new Point3dCollection();
foreach (ObjectId acObjIdVert in acPoly3d)
{
PolylineVertex3d acPolVer3d;
acPolVer3d = acTrans.GetObject(acObjIdVert,
OpenMode.ForRead) as PolylineVertex3d;

acPts3d.Add(acPolVer3d.Position);
}

// Display the Coordinates
Application.ShowAlertDialog("2D polyline (red): \n" +
acPts2d[0].ToString() + "\n" +
acPts2d[1].ToString() + "\n" +
acPts2d[2].ToString());

Application.ShowAlertDialog("3D polyline (blue): \n" +
acPts3d[0].ToString() + "\n" +
acPts3d[1].ToString() + "\n" +
acPts3d[2].ToString());
}
}

// Save the new object to the database
acTrans.Commit();
}
}

定义用户坐标系(.NET)

定义用户坐标系(UCS)对象以更改(0,0,0)原点的位置以及XY平面和Z轴的方向。您可以在3D空间中的任何位置定位和定向UCS,并且可以根据需要定义、保存和调用尽可能多的用户坐标系。坐标输入和显示相对于当前UCS。

要指示UCS的原点和方向,可以使用视口对象的IconAtOrigin特性或UCSICON系统变量在UCS原点处显示UCS图标。如果UCS图标处于启用状态(IconVisible特性)并且未显示在原点,则它将显示在由UCSORG系统变量定义的WCS坐标处。

可以使用UCST对象的Add方法创建新的用户坐标系。此方法需要四个值作为输入:原点坐标、X轴和Y轴上的坐标以及UCS的名称。

AutoCAD ® ActiveX Automation中的所有坐标都输入世界坐标系。使用GetUCSMatrix方法返回给定UCS的变换矩阵。使用此变换矩阵可找到等效的WCS坐标。

若要激活UCS,请使用Document对象上的ActiveUCS特性。如果对活动UCS进行了更改,则必须将新的UCS对象重置为活动UCS才能显示更改。要重置活动UCS,只需使用更新的UCS对象再次调用ActiveUCS属性。

创建新的UCS,使其处于活动状态,然后将点的坐标转换为UCS坐标

以下子例程将创建新的UCS并将其设置为图形的活动UCS。然后,它要求用户在图形中拾取一个点,并返回该点的WCS和UCS坐标。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
[CommandMethod("NewUCS")]
public static void NewUCS()
{
// Get the current document and database, and start a transaction
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Open the UCS table for read
UcsTable acUCSTbl;
acUCSTbl = acTrans.GetObject(acCurDb.UcsTableId,
OpenMode.ForRead) as UcsTable;

UcsTableRecord acUCSTblRec;

// Check to see if the "New_UCS" UCS table record exists
if (acUCSTbl.Has("New_UCS") == false)
{
acUCSTblRec = new UcsTableRecord();
acUCSTblRec.Name = "New_UCS";

// Open the UCSTable for write
acTrans.GetObject(acCurDb.UcsTableId, OpenMode.ForWrite);

// Add the new UCS table record
acUCSTbl.Add(acUCSTblRec);
acTrans.AddNewlyCreatedDBObject(acUCSTblRec, true);
}
else
{
acUCSTblRec = acTrans.GetObject(acUCSTbl["New_UCS"],
OpenMode.ForWrite) as UcsTableRecord;
}

acUCSTblRec.Origin = new Point3d(4, 5, 3);
acUCSTblRec.XAxis = new Vector3d(1, 0, 0);
acUCSTblRec.YAxis = new Vector3d(0, 1, 0);

// Open the active viewport
ViewportTableRecord acVportTblRec;
acVportTblRec = acTrans.GetObject(acDoc.Editor.ActiveViewportId,
OpenMode.ForWrite) as ViewportTableRecord;

// Display the UCS Icon at the origin of the current viewport
acVportTblRec.IconAtOrigin = true;
acVportTblRec.IconEnabled = true;

// Set the UCS current
acVportTblRec.SetUcs(acUCSTblRec.ObjectId);
acDoc.Editor.UpdateTiledViewportsFromDatabase();

// Display the name of the current UCS
UcsTableRecord acUCSTblRecActive;
acUCSTblRecActive = acTrans.GetObject(acVportTblRec.UcsName,
OpenMode.ForRead) as UcsTableRecord;

Application.ShowAlertDialog("The current UCS is: " +
acUCSTblRecActive.Name);

PromptPointResult pPtRes;
PromptPointOptions pPtOpts = new PromptPointOptions("");

// Prompt for a point
pPtOpts.Message = "\nEnter a point: ";
pPtRes = acDoc.Editor.GetPoint(pPtOpts);

Point3d pPt3dWCS;
Point3d pPt3dUCS;

// If a point was entered, then translate it to the current UCS
if (pPtRes.Status == PromptStatus.OK)
{
pPt3dWCS = pPtRes.Value;
pPt3dUCS = pPtRes.Value;

// Translate the point from the current UCS to the WCS
Matrix3d newMatrix = new Matrix3d();
newMatrix = Matrix3d.AlignCoordinateSystem(Point3d.Origin,
Vector3d.XAxis,
Vector3d.YAxis,
Vector3d.ZAxis,
acVportTblRec.Ucs.Origin,
acVportTblRec.Ucs.Xaxis,
acVportTblRec.Ucs.Yaxis,
acVportTblRec.Ucs.Zaxis);

pPt3dWCS = pPt3dWCS.TransformBy(newMatrix);

Application.ShowAlertDialog("The WCS coordinates are: \n" +
pPt3dWCS.ToString() + "\n" +
"The UCS coordinates are: \n" +
pPt3dUCS.ToString());
}

// Save the new objects to the database
acTrans.Commit();
}
}

转换坐标(.NET)

TransformBy 方法可以将点或位移从一个坐标系转换到另一个坐标系。您可以使用 AlignCoordinateSystem 方法指定要从哪个坐标系进行平移以及要平移到哪个坐标系。 AlignCoordinateSystem 方法需要以下内容:

  • 要转换的坐标系的原点

  • 三个3D向量,表示要从其进行平移的坐标系的X、Y和X轴

  • 要转换到的坐标系的原点

  • 三个3D向量,表示要转换到的坐标系的X、Y和X轴

  • WCS

    世界坐标系:参考坐标系。所有其他坐标系都是相对于WCS定义的,它永远不会更改。相对于WCS测量的值在其他坐标系的变化中保持稳定。除非另有说明,否则传入和传出.NET API中的方法和属性的所有点都在WCS中表示。

  • UCS

    用户坐标系(UCS):工作坐标系。用户指定UCS以简化绘图任务。传递给AutoCAD命令的所有点(包括从AutoLISP例程和外部函数返回的点)都是当前UCS中的点(除非用户在命令提示下在这些点前面加上 *)。如果希望应用程序将WCS、OCS或DCS中的坐标发送到AutoCAD命令,则必须首先通过调用转换将坐标转换为UCS,然后使用表示坐标值的 TransformBy 方法转换Point3d或Point 2d对象。

  • OCS

    对象坐标系(也称为实体坐标系或ECS):由某些方法和属性为Polyline2d和Polyline对象指定的点值在此坐标系中相对于对象表示。这些点通常会根据对象的预期用途转换为WCS、当前UCS或当前DCS。相反,WCS、UCS或DCS中的点必须先转换为OCS,然后才能通过相同的特性写入数据库。在将坐标转换为OCS或从OCS转换坐标时,必须考虑OCS的法线。

  • DCS

    显示坐标系:对象在显示之前进行变换的坐标系。DCS的原点是存储在AutoCAD系统变量TARGET中的点,其Z轴是观察方向。换句话说,视口始终是其DCS的平面视图。这些坐标可用于确定将在何处向用户显示某些内容。

  • PSDCS

    图纸空间DCS:此坐标系只能在模型空间视口的DCS之间进行变换。这本质上是一个2D变换,其中XY坐标始终缩放。因此,它可以用来找到两个坐标系之间的比例因子。PSDCS只能变换为模型空间视口。

将OCS坐标转换为WCS坐标

本示例在模型空间中创建一个对象。然后,将在OCS和WCS坐标中显示该顶点的第一个顶点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
[CommandMethod("TranslateCoordinates")]
public static void TranslateCoordinates()
{
// Get the current document and database, and start a transaction
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Open the Block table record for read
BlockTable acBlkTbl;
acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
OpenMode.ForRead) as BlockTable;

// Open the Block table record Model space for write
BlockTableRecord acBlkTblRec;
acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],
OpenMode.ForWrite) as BlockTableRecord;

// Create a 2D polyline with two segments (3 points)
using (Polyline2d acPoly2d = new Polyline2d())
{
// Add the new object to the block table record and the transaction
acBlkTblRec.AppendEntity(acPoly2d);
acTrans.AddNewlyCreatedDBObject(acPoly2d, true);

// Before adding vertexes, the polyline must be in the drawing
Point3dCollection acPts2dPoly = new Point3dCollection();
acPts2dPoly.Add(new Point3d(1, 1, 0));
acPts2dPoly.Add(new Point3d(1, 2, 0));
acPts2dPoly.Add(new Point3d(2, 2, 0));
acPts2dPoly.Add(new Point3d(3, 2, 0));
acPts2dPoly.Add(new Point3d(4, 4, 0));

foreach (Point3d acPt3d in acPts2dPoly)
{
Vertex2d acVer2d = new Vertex2d(acPt3d, 0, 0, 0, 0);
acPoly2d.AppendVertex(acVer2d);
acTrans.AddNewlyCreatedDBObject(acVer2d, true);
}

// Set the normal of the 2D polyline
acPoly2d.Normal = new Vector3d(0, 1, 2);

// Get the first coordinate of the 2D polyline
Point3dCollection acPts3d = new Point3dCollection();
Vertex2d acFirstVer = null;

foreach (ObjectId acObjIdVert in acPoly2d)
{
acFirstVer = acTrans.GetObject(acObjIdVert,
OpenMode.ForRead) as Vertex2d;

acPts3d.Add(acFirstVer.Position);

break;
}

// Get the first point of the polyline and
// use the eleveation for the Z value
Point3d pFirstVer = new Point3d(acFirstVer.Position.X,
acFirstVer.Position.Y,
acPoly2d.Elevation);

// Translate the OCS to WCS
Matrix3d mWPlane = Matrix3d.WorldToPlane(acPoly2d.Normal);
Point3d pWCSPt = pFirstVer.TransformBy(mWPlane);

Application.ShowAlertDialog("The first vertex has the following " +
"coordinates:" +
"\nOCS: " + pFirstVer.ToString() +
"\nWCS: " + pWCSPt.ToString());
}

// Save the new objects to the database
acTrans.Commit();
}
}

创建3D对象(.NET)

AutoCAD支持三种类型的三维建模:线框、曲面和实体。每种类型都有自己的创建和编辑技术。

本节中的主题

  • 创建线框(.NET)
  • 创建网格(.NET)
  • 创建多面网格(.NET)
  • 创建实体(.NET)

创建线框(.NET)

使用AutoCAD,您可以通过将任何二维平面对象定位在三维空间中的任何位置来创建线框模型。可以使用以下几种方法在三维空间中定位二维对象:

  • 通过输入三维点创建对象。输入定义点的XYZ位置的坐标。
  • 通过定义UCS,设定要在其上绘制对象的默认构建平面(XY平面)。
  • 创建对象后,将其移动到三维空间中的正确方向。

此外,还可以创建一些线框对象,如直线和三维多段线,这些对象可以存在于所有三个维中。

创建网格(.NET)

矩形网格( PolygonMesh object)使用平面小平面表示对象的表面。网格的面的密度或数量是根据M和N个顶点的矩阵来定义的,类似于由列和行组成的网格。M和N分别指定任何给定顶点的列和行位置。可以在二维和三维中创建网格,但它们主要用于三维。

创建 PolygonMesh 对象的实例,然后为新网格指定顶点的密度和放置。此方法可选地采用六个值:要创建的多边形网格的类型、定义M和N方向上的顶点数的两个整数、包含网格中所有顶点坐标的点集合,以及定义网格在M或N方向上是否闭合的两个布尔值。

创建PolygonMesh后,使用 IsMClosed 和 NClosed 属性关闭网格。

创建多边形网格
本示例创建一个4×4多边形网格。然后调整活动视口的方向,以便更容易查看网格的三维特性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
[CommandMethod("Create3DMesh")]
public static void Create3DMesh()
{
// Get the current document and database, and start a transaction
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Open the Block table record for read
BlockTable acBlkTbl;
acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
OpenMode.ForRead) as BlockTable;

// Open the Block table record Model space for write
BlockTableRecord acBlkTblRec;
acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],
OpenMode.ForWrite) as BlockTableRecord;

// Create a polygon mesh
using (PolygonMesh acPolyMesh = new PolygonMesh())
{
acPolyMesh.MSize = 4;
acPolyMesh.NSize = 4;

// Add the new object to the block table record and the transaction
acBlkTblRec.AppendEntity(acPolyMesh);
acTrans.AddNewlyCreatedDBObject(acPolyMesh, true);

// Before adding vertexes, the polyline must be in the drawing
Point3dCollection acPts3dPMesh = new Point3dCollection();
acPts3dPMesh.Add(new Point3d(0, 0, 0));
acPts3dPMesh.Add(new Point3d(2, 0, 1));
acPts3dPMesh.Add(new Point3d(4, 0, 0));
acPts3dPMesh.Add(new Point3d(6, 0, 1));

acPts3dPMesh.Add(new Point3d(0, 2, 0));
acPts3dPMesh.Add(new Point3d(2, 2, 1));
acPts3dPMesh.Add(new Point3d(4, 2, 0));
acPts3dPMesh.Add(new Point3d(6, 2, 1));

acPts3dPMesh.Add(new Point3d(0, 4, 0));
acPts3dPMesh.Add(new Point3d(2, 4, 1));
acPts3dPMesh.Add(new Point3d(4, 4, 0));
acPts3dPMesh.Add(new Point3d(6, 4, 0));

acPts3dPMesh.Add(new Point3d(0, 6, 0));
acPts3dPMesh.Add(new Point3d(2, 6, 1));
acPts3dPMesh.Add(new Point3d(4, 6, 0));
acPts3dPMesh.Add(new Point3d(6, 6, 0));

foreach (Point3d acPt3d in acPts3dPMesh)
{
PolygonMeshVertex acPMeshVer = new PolygonMeshVertex(acPt3d);
acPolyMesh.AppendVertex(acPMeshVer);
acTrans.AddNewlyCreatedDBObject(acPMeshVer, true);
}
}

// Open the active viewport
ViewportTableRecord acVportTblRec;
acVportTblRec = acTrans.GetObject(acDoc.Editor.ActiveViewportId,
OpenMode.ForWrite) as ViewportTableRecord;

// Rotate the view direction of the current viewport
acVportTblRec.ViewDirection = new Vector3d(-1, -1, 1);
acDoc.Editor.UpdateTiledViewportsFromDatabase();

// Save the new objects to the database
acTrans.Commit();
}
}

创建多面网格(.NET)

多面网格表示由能够具有多个顶点的面定义的对象曲面。创建多面网格类似于创建矩形网格。通过创建 PolyFaceMesh 对象的实例来创建多面网格。 PolyFaceMesh 对象的构造函数不接受任何参数。若要将顶点添加到多面网格,请创建一个 PolyFaceMeshVertex 并使用 AppendVertex 方法将其添加到 PolyFaceMesh 对象。

创建多面网格时,可以将特定边设置为不可见、将其指定给层或为其指定颜色。要使边不可见,请创建 FaceRecord 的实例并设置哪些边应不可见,然后使用 AppendFaceRecord 方法将 FaceRecord 对象附加到 PolyFaceMesh 对象。

创建多面网格
此示例创建 PolyfaceMesh 对象并更改活动视口的查看方向以显示网格的三维特性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
[CommandMethod("CreatePolyfaceMesh")]
public static void CreatePolyfaceMesh()
{
// Get the current document and database, and start a transaction
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Open the Block table record for read
BlockTable acBlkTbl;
acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
OpenMode.ForRead) as BlockTable;

// Open the Block table record Model space for write
BlockTableRecord acBlkTblRec;
acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],
OpenMode.ForWrite) as BlockTableRecord;

// Create a polyface mesh
using (PolyFaceMesh acPFaceMesh = new PolyFaceMesh())
{
// Add the new object to the block table record and the transaction
acBlkTblRec.AppendEntity(acPFaceMesh);
acTrans.AddNewlyCreatedDBObject(acPFaceMesh, true);

// Before adding vertexes, the polyline must be in the drawing
Point3dCollection acPts3dPFMesh = new Point3dCollection();
acPts3dPFMesh.Add(new Point3d(4, 7, 0));
acPts3dPFMesh.Add(new Point3d(5, 7, 0));
acPts3dPFMesh.Add(new Point3d(6, 7, 0));

acPts3dPFMesh.Add(new Point3d(4, 6, 0));
acPts3dPFMesh.Add(new Point3d(5, 6, 0));
acPts3dPFMesh.Add(new Point3d(6, 6, 1));

foreach (Point3d acPt3d in acPts3dPFMesh)
{
PolyFaceMeshVertex acPMeshVer = new PolyFaceMeshVertex(acPt3d);
acPFaceMesh.AppendVertex(acPMeshVer);
acTrans.AddNewlyCreatedDBObject(acPMeshVer, true);
}

using (FaceRecord acFaceRec1 = new FaceRecord(1, 2, 5, 4))
{
acPFaceMesh.AppendFaceRecord(acFaceRec1);
acTrans.AddNewlyCreatedDBObject(acFaceRec1, true);
}

using (FaceRecord acFaceRec2 = new FaceRecord(2, 3, 6, 5))
{
acPFaceMesh.AppendFaceRecord(acFaceRec2);
acTrans.AddNewlyCreatedDBObject(acFaceRec2, true);
}
}

// Open the active viewport
ViewportTableRecord acVportTblRec;
acVportTblRec = acTrans.GetObject(acDoc.Editor.ActiveViewportId,
OpenMode.ForWrite) as ViewportTableRecord;

// Rotate the view direction of the current viewport
acVportTblRec.ViewDirection = new Vector3d(-1, -1, 1);
acDoc.Editor.UpdateTiledViewportsFromDatabase();

// Save the new objects to the database
acTrans.Commit();
}
}

创建实体(.NET)

实体对象(Solid3d对象)表示对象的整个体积。实体是3D建模类型中信息最完整、模糊性最小的类型。复杂的实体形状也比线框和网格更容易构造和编辑。

您可以使用 Solid3d 对象的成员方法和属性创建基本的实体形状,例如长方体、球体和楔形等。也可以沿路径沿着拉伸面域对象或绕轴旋转二维对象。

与网格一样,实体将显示为线框,直到您对其进行隐藏、着色或渲染。此外,还可以分析实体的质量属性(体积、惯性矩、重心等)。使用以下 MassProperties 属性,可以查询与 Solid3d 对象关联的 Solid3dMassProperties 对象。3#对象包含以下属性,可用于分析实体: MomentOfInertia 、 PrincipalAxes 、 PrincipalMoments 、 ProductOfInertia 、 RadiiOfGyration 和 Volume.

实体的显示受当前视觉样式和与三维建模相关的系统变量的影响。影响实体显示的系统变量包括ISOLINES和FACETRES。ISOLINES控制用于可视化线框弯曲部分的镶嵌线数量,而FACETRES调整着色和隐藏线对象的平滑度。

创建楔体
下面的示例创建楔形实体。活动视口的查看方向将更新,以显示楔体的三维特性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
[CommandMethod("CreateWedge")]
public static void CreateWedge()
{
// Get the current document and database, and start a transaction
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Open the Block table record for read
BlockTable acBlkTbl;
acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
OpenMode.ForRead) as BlockTable;

// Open the Block table record Model space for write
BlockTableRecord acBlkTblRec;
acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],
OpenMode.ForWrite) as BlockTableRecord;

// Create a 3D solid wedge
using (Solid3d acSol3D = new Solid3d())
{
acSol3D.CreateWedge(10, 15, 20);

// Position the center of the 3D solid at (5,5,0)
acSol3D.TransformBy(Matrix3d.Displacement(new Point3d(5, 5, 0) -
Point3d.Origin));

// Add the new object to the block table record and the transaction
acBlkTblRec.AppendEntity(acSol3D);
acTrans.AddNewlyCreatedDBObject(acSol3D, true);
}

// Open the active viewport
ViewportTableRecord acVportTblRec;
acVportTblRec = acTrans.GetObject(acDoc.Editor.ActiveViewportId,
OpenMode.ForWrite) as ViewportTableRecord;

// Rotate the view direction of the current viewport
acVportTblRec.ViewDirection = new Vector3d(-1, -1, 1);
acDoc.Editor.UpdateTiledViewportsFromDatabase();

// Save the new objects to the database
acTrans.Commit();
}
}

在3D中编辑(.NET)

本节介绍如何通过旋转、阵列和镜像等方式编辑3D对象。

本节中的主题

  • 在3D中旋转(.NET)
  • 3D阵列(.NET)
  • 沿着平面镜像对象(.NET)

在3D中旋转(.NET)

使用对象的 TransformBy 方法和Matrix的 Rotation 方法,您可以在2D中围绕指定点旋转对象。2D对象的旋转方向围绕Z轴。对于3D对象,旋转轴不限于Z轴。当使用 Rotation 方法而不是使用Z轴作为旋转轴时,需要指定特定的3D向量。

img

创建3D长方体并绕轴旋转
此示例创建一个3D长方体。然后定义旋转轴,最后将长方体绕该轴旋转30度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
[CommandMethod("Rotate_3DBox")]
public static void Rotate_3DBox()
{
// Get the current document and database, and start a transaction
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Open the Block table for read
BlockTable acBlkTbl;
acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
OpenMode.ForRead) as BlockTable;

// Open the Block table record Model space for write
BlockTableRecord acBlkTblRec;
acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],
OpenMode.ForWrite) as BlockTableRecord;

// Create a 3D solid box
using (Solid3d acSol3D = new Solid3d())
{
acSol3D.CreateBox(5, 7, 10);

// Position the center of the 3D solid at (5,5,0)
acSol3D.TransformBy(Matrix3d.Displacement(new Point3d(5, 5, 0) -
Point3d.Origin));

Matrix3d curUCSMatrix = acDoc.Editor.CurrentUserCoordinateSystem;
CoordinateSystem3d curUCS = curUCSMatrix.CoordinateSystem3d;

// Rotate the 3D solid 30 degrees around the axis that is
// defined by the points (-3,4,0) and (-3,-4,0)
Vector3d vRot = new Point3d(-3, 4, 0).
GetVectorTo(new Point3d(-3, -4, 0));

acSol3D.TransformBy(Matrix3d.Rotation(0.5236,
vRot,
new Point3d(-3, 4, 0)));

// Add the new object to the block table record and the transaction
acBlkTblRec.AppendEntity(acSol3D);
acTrans.AddNewlyCreatedDBObject(acSol3D, true);
}

// Save the new objects to the database
acTrans.Commit();
}
}

3D阵列(.NET)

使用对象的 TransformBy 和 Clone 方法,可以创建3D矩形阵列。除了像指定二维矩形阵列那样指定列数(X方向)和行数(Y方向)外,还可以指定级别数(Z方向)。

创建三维矩形阵列
此示例创建一个圆,然后使用该圆创建一个由四行、四列和三层圆组成的矩形阵列。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
static Point2d PolarPoints(Point2d pPt, double dAng, double dDist)
{
return new Point2d(pPt.X + dDist * Math.Cos(dAng),
pPt.Y + dDist * Math.Sin(dAng));
}

[CommandMethod("CreateRectangular3DArray")]
public static void CreateRectangular3DArray()
{
// Get the current document and database, and start a transaction
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Open the Block table record for read
BlockTable acBlkTbl;
acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
OpenMode.ForRead) as BlockTable;

// Open the Block table record Model space for write
BlockTableRecord acBlkTblRec;
acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],
OpenMode.ForWrite) as BlockTableRecord;

// Create a circle that is at 2,2 with a radius of 0.5
using (Circle acCirc = new Circle())
{
acCirc.Center = new Point3d(2, 2, 0);
acCirc.Radius = 0.5;

// Add the new object to the block table record and the transaction
acBlkTblRec.AppendEntity(acCirc);
acTrans.AddNewlyCreatedDBObject(acCirc, true);

// Create a rectangular array with 4 rows, 4 columns, and 3 levels
int nRows = 4;
int nColumns = 4;
int nLevels = 3;

// Set the row, column, and level offsets along with the base array angle
double dRowOffset = 1;
double dColumnOffset = 1;
double dLevelsOffset = 4;
double dArrayAng = 0;

// Get the angle from X for the current UCS
Matrix3d curUCSMatrix = acDoc.Editor.CurrentUserCoordinateSystem;
CoordinateSystem3d curUCS = curUCSMatrix.CoordinateSystem3d;
Vector2d acVec2dAng = new Vector2d(curUCS.Xaxis.X,
curUCS.Xaxis.Y);

// If the UCS is rotated, adjust the array angle accordingly
dArrayAng = dArrayAng + acVec2dAng.Angle;

// Use the upper-left corner of the objects extents for the array base point
Extents3d acExts = acCirc.Bounds.GetValueOrDefault();
Point2d acPt2dArrayBase = new Point2d(acExts.MinPoint.X,
acExts.MaxPoint.Y);

// Track the objects created for each column
DBObjectCollection acDBObjCollCols = new DBObjectCollection();
acDBObjCollCols.Add(acCirc);

// Create the number of objects for the first column
int nColumnsCount = 1;
while (nColumns > nColumnsCount)
{
Entity acEntClone = acCirc.Clone() as Entity;
acDBObjCollCols.Add(acEntClone);

// Caclucate the new point for the copied object (move)
Point2d acPt2dTo = PolarPoints(acPt2dArrayBase,
dArrayAng,
dColumnOffset * nColumnsCount);

Vector2d acVec2d = acPt2dArrayBase.GetVectorTo(acPt2dTo);
Vector3d acVec3d = new Vector3d(acVec2d.X, acVec2d.Y, 0);
acEntClone.TransformBy(Matrix3d.Displacement(acVec3d));

acBlkTblRec.AppendEntity(acEntClone);
acTrans.AddNewlyCreatedDBObject(acEntClone, true);

nColumnsCount = nColumnsCount + 1;
}

// Set a value in radians for 90 degrees
double dAng = 1.5708;

// Track the objects created for each row and column
DBObjectCollection acDBObjCollLvls = new DBObjectCollection();

foreach (DBObject acObj in acDBObjCollCols)
{
acDBObjCollLvls.Add(acObj);
}

// Create the number of objects for each row
foreach (Entity acEnt in acDBObjCollCols)
{
int nRowsCount = 1;

while (nRows > nRowsCount)
{
Entity acEntClone = acEnt.Clone() as Entity;
acDBObjCollLvls.Add(acEntClone);

// Caclucate the new point for the copied object (move)
Point2d acPt2dTo = PolarPoints(acPt2dArrayBase,
dArrayAng + dAng,
dRowOffset * nRowsCount);

Vector2d acVec2d = acPt2dArrayBase.GetVectorTo(acPt2dTo);
Vector3d acVec3d = new Vector3d(acVec2d.X, acVec2d.Y, 0);
acEntClone.TransformBy(Matrix3d.Displacement(acVec3d));

acBlkTblRec.AppendEntity(acEntClone);
acTrans.AddNewlyCreatedDBObject(acEntClone, true);

nRowsCount = nRowsCount + 1;
}
}

// Create the number of levels for a 3D array
foreach (Entity acEnt in acDBObjCollLvls)
{
int nLvlsCount = 1;

while (nLevels > nLvlsCount)
{
Entity acEntClone = acEnt.Clone() as Entity;

Vector3d acVec3d = new Vector3d(0, 0, dLevelsOffset * nLvlsCount);
acEntClone.TransformBy(Matrix3d.Displacement(acVec3d));

acBlkTblRec.AppendEntity(acEntClone);
acTrans.AddNewlyCreatedDBObject(acEntClone, true);

nLvlsCount = nLvlsCount + 1;
}
}
}

// Save the new objects to the database
acTrans.Commit();
}
}

沿着平面镜像对象(.NET)

使用对象的 TransformBy 方法和矩阵的 Mirroring 方法,可以沿由三个点指定的指定镜像平面沿着镜像对象。

img

3D镜像
本示例在模型空间中创建一个长方体。然后围绕平面镜像长方体,并将镜像的长方体着色为红色。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
[CommandMethod("MirrorABox3D")]
public static void MirrorABox3D()
{
// Get the current document and database, and start a transaction
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Open the Block table record for read
BlockTable acBlkTbl;
acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
OpenMode.ForRead) as BlockTable;

// Open the Block table record Model space for write
BlockTableRecord acBlkTblRec;
acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],
OpenMode.ForWrite) as BlockTableRecord;

// Create a 3D solid box
using (Solid3d acSol3D = new Solid3d())
{
acSol3D.CreateBox(5, 7, 10);

// Position the center of the 3D solid at (5,5,0)
acSol3D.TransformBy(Matrix3d.Displacement(new Point3d(5, 5, 0) -
Point3d.Origin));

// Add the new object to the block table record and the transaction
acBlkTblRec.AppendEntity(acSol3D);
acTrans.AddNewlyCreatedDBObject(acSol3D, true);

// Create a copy of the original 3D solid and change the color of the copy
Solid3d acSol3DCopy = acSol3D.Clone() as Solid3d;
acSol3DCopy.ColorIndex = 1;

// Define the mirror plane
Plane acPlane = new Plane(new Point3d(1.25, 0, 0),
new Point3d(1.25, 2, 0),
new Point3d(1.25, 2, 2));

// Mirror the 3D solid across the plane
acSol3DCopy.TransformBy(Matrix3d.Mirroring(acPlane));

// Add the new object to the block table record and the transaction
acBlkTblRec.AppendEntity(acSol3DCopy);
acTrans.AddNewlyCreatedDBObject(acSol3DCopy, true);
}

// Save the new objects to the database
acTrans.Commit();
}
}

编辑三维实体(.NET)

创建实体后,可以通过合并或减去实体来创建更复杂的形状。您可以连接实体、将实体彼此相减或查找实体的公共体积(重叠部分)。使用 BooleanOperation 方法执行这些组合。使用 CheckInterference 方法可以确定两个实体是否重叠。

img

通过获得实体的2D横截面或将实体切成两片来进一步修改实体。使用 GetSection 方法查找实体的横截面,使用 Slice 方法将实体切成两部分。

求两个固体之间的干涉
此示例创建一个长方体和圆柱体。然后查找两个实体之间的干涉,并根据该干涉创建新实体。为便于查看,框的颜色为白色,圆柱体的颜色为青色,干涉实体的颜色为红色。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
[CommandMethod("FindInterferenceBetweenSolids")]
public static void FindInterferenceBetweenSolids()
{
// Get the current document and database, and start a transaction
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Open the Block table record for read
BlockTable acBlkTbl;
acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
OpenMode.ForRead) as BlockTable;

// Open the Block table record Model space for write
BlockTableRecord acBlkTblRec;
acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],
OpenMode.ForWrite) as BlockTableRecord;

// Create a 3D solid box
using (Solid3d acSol3DBox = new Solid3d())
{
acSol3DBox.CreateBox(5, 7, 10);
acSol3DBox.ColorIndex = 7;

// Position the center of the 3D solid at (5,5,0)
acSol3DBox.TransformBy(Matrix3d.Displacement(new Point3d(5, 5, 0) -
Point3d.Origin));

// Add the new object to the block table record and the transaction
acBlkTblRec.AppendEntity(acSol3DBox);
acTrans.AddNewlyCreatedDBObject(acSol3DBox, true);

// Create a 3D solid cylinder
// 3D solids are created at (0,0,0) so there is no need to move it
using (Solid3d acSol3DCyl = new Solid3d())
{
acSol3DCyl.CreateFrustum(20, 5, 5, 5);
acSol3DCyl.ColorIndex = 4;

// Add the new object to the block table record and the transaction
acBlkTblRec.AppendEntity(acSol3DCyl);
acTrans.AddNewlyCreatedDBObject(acSol3DCyl, true);

// Create a 3D solid from the interference of the box and cylinder
Solid3d acSol3DCopy = acSol3DCyl.Clone() as Solid3d;

// Check to see if the 3D solids overlap
if (acSol3DCopy.CheckInterference(acSol3DBox) == true)
{
acSol3DCopy.BooleanOperation(BooleanOperationType.BoolIntersect,
acSol3DBox.Clone() as Solid3d);

acSol3DCopy.ColorIndex = 1;
}

// Add the new object to the block table record and the transaction
acBlkTblRec.AppendEntity(acSol3DCopy);
acTrans.AddNewlyCreatedDBObject(acSol3DCopy, true);
}
}

// Save the new objects to the database
acTrans.Commit();
}
}

将一个实体切成两个实体
本示例在模型空间中创建一个长方体。然后,它基于由三个点定义的平面对长方体进行切片。切片将作为3DSolid返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
[CommandMethod("SliceABox")]
public static void SliceABox()
{
// Get the current document and database, and start a transaction
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Open the Block table record for read
BlockTable acBlkTbl;
acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
OpenMode.ForRead) as BlockTable;

// Open the Block table record Model space for write
BlockTableRecord acBlkTblRec;
acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],
OpenMode.ForWrite) as BlockTableRecord;

// Create a 3D solid box
using (Solid3d acSol3D = new Solid3d())
{
acSol3D.CreateBox(5, 7, 10);
acSol3D.ColorIndex = 7;

// Position the center of the 3D solid at (5,5,0)
acSol3D.TransformBy(Matrix3d.Displacement(new Point3d(5, 5, 0) -
Point3d.Origin));

// Add the new object to the block table record and the transaction
acBlkTblRec.AppendEntity(acSol3D);
acTrans.AddNewlyCreatedDBObject(acSol3D, true);

// Define the mirror plane
Plane acPlane = new Plane(new Point3d(1.5, 7.5, 0),
new Point3d(1.5, 7.5, 10),
new Point3d(8.5, 2.5, 10));

Solid3d acSol3DSlice = acSol3D.Slice(acPlane, true);
acSol3DSlice.ColorIndex = 1;

// Add the new object to the block table record and the transaction
acBlkTblRec.AppendEntity(acSol3DSlice);
acTrans.AddNewlyCreatedDBObject(acSol3DSlice, true);
}

// Save the new objects to the database
acTrans.Commit();
}
}

注:翻译自ObjectARX: Managed .NET Developer’s Guide,且只保留了C#部分的代码