在CAD中,一般的面片都是3D Face。3D Face是由四个顶点形成,在实际运用中为了能更好的显示,一般将这四个点中的两个点重合,形成三角形。在CAD中,一般认为,如果绘制面的时候是按逆时针方向,则为正面,反之为反面。具体来说就是,如果3D Face地四个顶点是按照逆时针方向的顺序排列,则该面为正面;按照顺时针方向顺序排列为反面。
正反面非常重要,如在3DMAX中,如果需要以地形的表面为基础高程,则地物将会在地形表面上,如果是反面,则地形向下,即在地下,看不见!所以在导入地形前,需要进行一些相应的前处理工作。下面的程序代码就是如何实现正反面判断、如何转换正反面的:
Public Class 更正CAD中面片法线方向
Public AcadApp As AutoCAD.AcadApplication
Public Sub 启动CAD()
On Error Resume Next
AcadApp = GetObject(, "AutoCAD.Application")
If Err.Number Then
Err.Clear()
AcadApp = CreateObject("AutoCAD.Application")
End If
AcadApp.Visible = True
AcadApp.WindowState = AutoCAD.AcWindowState.acMax
AppActivate(AcadApp.Caption)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Call 启动CAD()
Dim sset As AutoCAD.AcadSelectionSet
sset = AcadApp.ActiveDocument.SelectionSets.Add("NewSelectionSet01")
sset.SelectOnScreen()
Dim ent As Object
Dim count As Integer
For Each ent In sset
If ent.objectname = "AcDbFace" Then
Dim ss As AutoCAD.Acad3DFace
ss = ent
Dim i As Integer
Dim point01(2), point02(2), point03(2), point04(2), newArrayPoints(3, 2) As Double
For i = 0 To 2
point01(i) = ss.Coordinate(0)(i)
point02(i) = ss.Coordinate(1)(i)
point03(i) = ss.Coordinate(2)(i)
point04(i) = ss.Coordinate(3)(i)
Next
If Is3Points(point01, point02, point03, point04, newArrayPoints) Then
ss.Delete()
Dim p01(2), p02(2), p03(2) As Double
Dim j As Integer
For j = 0 To 2
p01(j) = newArrayPoints(0, j)
p02(j) = newArrayPoints(1, j)
p03(j) = newArrayPoints(2, j)
Next
AcadApp.ActiveDocument.ModelSpace.Add3DFace(p01, p03, p02, p01)
count = count + 1
End If
End If
Next
MsgBox("共有" & count.ToString() & "个反面")
AcadApp.ActiveDocument.SelectionSets.Item("NewSelectionSet01").Delete()
End Sub
Private Function IsNotUp(ByVal vector01() As Double, ByVal vector02() As Double) As Boolean '检验两个向量的向量积是否向上
Dim Zresult As Double
Zresult = vector01(0) * vector02(1) - vector01(1) * vector02(0)
If Zresult >= 0 Then
Return True
End If
Return False
End Function
Private Sub DoVector3(ByVal point01() As Double, ByVal point02() As Double, ByVal point03() As Double, ByRef vector01() As Double, ByRef vector02() As Double) '根据三个点得到两个矢量
vector01(0) = point02(0) - point01(0)
vector01(1) = point02(1) - point01(1)
vector01(2) = point02(2) - point01(2)
vector02(0) = point03(0) - point02(0)
vector02(1) = point03(1) - point02(1)
vector02(2) = point03(2) - point02(2)
End Sub
Private Function Is3Points(ByVal point01() As Double, ByVal point02() As Double, ByVal point03() As Double, ByVal point04() As Double, ByRef newArrayPoints(,) As Double) As Boolean
Is3Points = False
Dim i, j As Integer
Dim AllPoints(3, 2) As Double
For i = 0 To 2
AllPoints(0, i) = point01(i)
Next
For i = 0 To 2
AllPoints(1, i) = point02(i)
Next
For i = 0 To 2
AllPoints(2, i) = point03(i)
Next
For i = 0 To 2
AllPoints(3, i) = point04(i)
Next
For i = 0 To 3
For j = 0 To 3
If j = i Then Continue For
If AllPoints(i, 0) = AllPoints(j, 0) And AllPoints(i, 1) = AllPoints(j, 1) And AllPoints(i, 2) = AllPoints(j, 2) Then
Is3Points = True
GoTo handle01
End If
Next
Next
handle01:
If j < 3 Then
Dim k As Integer
For k = 0 To 2 - j
For i = 0 To 2
AllPoints(j + k, i) = AllPoints(j + k + 1, i)
Next
Next
End If
Dim vector01(2), vector02(2) As Double
Dim p01(2), p02(2), p03(2) As Double
For i = 0 To 2
p01(i) = AllPoints(0, i)
p02(i) = AllPoints(1, i)
p03(i) = AllPoints(2, i)
Next
DoVector3(p01, p02, p03, vector01, vector02)
If (IsNotUp(vector01, vector02)) Then
Is3Points = False
End If
Dim s As String
For i = 0 To 3
s = s + AllPoints(i, 0).ToString() + "," + AllPoints(i, 1).ToString() + "," + AllPoints(i, 2).ToString() + Chr(13)
Next
s = s + vector01(0).ToString() + "," + vector01(1).ToString() + "," + vector01(2).ToString() + Chr(13)
s = s + vector02(0).ToString() + "," + vector02(1).ToString() + "," + vector02(2).ToString() + Chr(13)
RichTextBox1.Text = s
For i = 0 To 3
For j = 0 To 2
newArrayPoints(i, j) = AllPoints(i, j)
Next
Next
End Function
End Class
正反面非常重要,如在3DMAX中,如果需要以地形的表面为基础高程,则地物将会在地形表面上,如果是反面,则地形向下,即在地下,看不见!所以在导入地形前,需要进行一些相应的前处理工作。下面的程序代码就是如何实现正反面判断、如何转换正反面的:
Public Class 更正CAD中面片法线方向
Public AcadApp As AutoCAD.AcadApplication
Public Sub 启动CAD()
On Error Resume Next
AcadApp = GetObject(, "AutoCAD.Application")
If Err.Number Then
Err.Clear()
AcadApp = CreateObject("AutoCAD.Application")
End If
AcadApp.Visible = True
AcadApp.WindowState = AutoCAD.AcWindowState.acMax
AppActivate(AcadApp.Caption)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Call 启动CAD()
Dim sset As AutoCAD.AcadSelectionSet
sset = AcadApp.ActiveDocument.SelectionSets.Add("NewSelectionSet01")
sset.SelectOnScreen()
Dim ent As Object
Dim count As Integer
For Each ent In sset
If ent.objectname = "AcDbFace" Then
Dim ss As AutoCAD.Acad3DFace
ss = ent
Dim i As Integer
Dim point01(2), point02(2), point03(2), point04(2), newArrayPoints(3, 2) As Double
For i = 0 To 2
point01(i) = ss.Coordinate(0)(i)
point02(i) = ss.Coordinate(1)(i)
point03(i) = ss.Coordinate(2)(i)
point04(i) = ss.Coordinate(3)(i)
Next
If Is3Points(point01, point02, point03, point04, newArrayPoints) Then
ss.Delete()
Dim p01(2), p02(2), p03(2) As Double
Dim j As Integer
For j = 0 To 2
p01(j) = newArrayPoints(0, j)
p02(j) = newArrayPoints(1, j)
p03(j) = newArrayPoints(2, j)
Next
AcadApp.ActiveDocument.ModelSpace.Add3DFace(p01, p03, p02, p01)
count = count + 1
End If
End If
Next
MsgBox("共有" & count.ToString() & "个反面")
AcadApp.ActiveDocument.SelectionSets.Item("NewSelectionSet01").Delete()
End Sub
Private Function IsNotUp(ByVal vector01() As Double, ByVal vector02() As Double) As Boolean '检验两个向量的向量积是否向上
Dim Zresult As Double
Zresult = vector01(0) * vector02(1) - vector01(1) * vector02(0)
If Zresult >= 0 Then
Return True
End If
Return False
End Function
Private Sub DoVector3(ByVal point01() As Double, ByVal point02() As Double, ByVal point03() As Double, ByRef vector01() As Double, ByRef vector02() As Double) '根据三个点得到两个矢量
vector01(0) = point02(0) - point01(0)
vector01(1) = point02(1) - point01(1)
vector01(2) = point02(2) - point01(2)
vector02(0) = point03(0) - point02(0)
vector02(1) = point03(1) - point02(1)
vector02(2) = point03(2) - point02(2)
End Sub
Private Function Is3Points(ByVal point01() As Double, ByVal point02() As Double, ByVal point03() As Double, ByVal point04() As Double, ByRef newArrayPoints(,) As Double) As Boolean
Is3Points = False
Dim i, j As Integer
Dim AllPoints(3, 2) As Double
For i = 0 To 2
AllPoints(0, i) = point01(i)
Next
For i = 0 To 2
AllPoints(1, i) = point02(i)
Next
For i = 0 To 2
AllPoints(2, i) = point03(i)
Next
For i = 0 To 2
AllPoints(3, i) = point04(i)
Next
For i = 0 To 3
For j = 0 To 3
If j = i Then Continue For
If AllPoints(i, 0) = AllPoints(j, 0) And AllPoints(i, 1) = AllPoints(j, 1) And AllPoints(i, 2) = AllPoints(j, 2) Then
Is3Points = True
GoTo handle01
End If
Next
Next
handle01:
If j < 3 Then
Dim k As Integer
For k = 0 To 2 - j
For i = 0 To 2
AllPoints(j + k, i) = AllPoints(j + k + 1, i)
Next
Next
End If
Dim vector01(2), vector02(2) As Double
Dim p01(2), p02(2), p03(2) As Double
For i = 0 To 2
p01(i) = AllPoints(0, i)
p02(i) = AllPoints(1, i)
p03(i) = AllPoints(2, i)
Next
DoVector3(p01, p02, p03, vector01, vector02)
If (IsNotUp(vector01, vector02)) Then
Is3Points = False
End If
Dim s As String
For i = 0 To 3
s = s + AllPoints(i, 0).ToString() + "," + AllPoints(i, 1).ToString() + "," + AllPoints(i, 2).ToString() + Chr(13)
Next
s = s + vector01(0).ToString() + "," + vector01(1).ToString() + "," + vector01(2).ToString() + Chr(13)
s = s + vector02(0).ToString() + "," + vector02(1).ToString() + "," + vector02(2).ToString() + Chr(13)
RichTextBox1.Text = s
For i = 0 To 3
For j = 0 To 2
newArrayPoints(i, j) = AllPoints(i, j)
Next
Next
End Function
End Class
这个程序的核心就是如何判断正反面,在此我设计的是两个矢量相乘,即求向量积,判断k方向的系数的正负,从而判断面的方向.正数对应的是正面,负数对应的是负面. |