Michael2 发表于 2020-4-7 10:16:35

我想确定管几何可以我

大家好。
我试图在AutoCAD Mecanical 2018文件中查找管段尺寸(直径)和长度。在所有情况下,管段都是实心3D类型,具有空心中心。我很快地画了一些代码来做这件事,它似乎工作,但我不是很聪明,所以它将只工作,如果管道沿Z轴定向。很简单。我可以用一堆“如果/那么”让它在其他正交视图中工作,但这并不适用于所有情况。
我的问题是,我需要它在任何方向上与管段一起工作。
这些管道将与许多其他非管道实体混合在一起,因此必须将对象识别为管道,然后必须确定其直径。
请注意,我不能依赖于管道末端是方形的,所以我不认为我可以通过brep.faces迭代查找某个直径的圆形面或做类似的事情。
我附加了一个dwg文件,其中包含两个管道段。一个简单的沿Z轴定向的例子,一个最坏的例子,我在所有三个轴上稍微旋转了管段,然后我切掉了末端。
下面是我测试的初始代码(它适用于Z对齐的管道段):
      
      Dim sf = New SelectionFilter(New TypedValue() {New TypedValue(CInt(DxfCode.Start), "3DSOLID")})
      Dim selResult As PromptSelectionResult = acEd.SelectAll(sf)

      Dim PipeODs As New Dictionary(Of String, Double)    ' (OD, Nom)
      PipeODs.Add(CDbl(0.84).ToString, 0.5)
      PipeODs.Add(CDbl(1).ToString, 0.75)
      PipeODs.Add(CDbl(1.3125).ToString, 1)
      PipeODs.Add(CDbl(1.875).ToString, 1.5)
      PipeODs.Add(CDbl(2.375).ToString, 2)
      PipeODs.Add(CDbl(3.5).ToString, 3)
      PipeODs.Add(CDbl(4.5).ToString, 4)
      PipeODs.Add(CDbl(6.625).ToString, 6)
      PipeODs.Add(CDbl(8.625).ToString, 8)
      PipeODs.Add(CDbl(10.75).ToString, 10)
        Using acDoc.LockDocument()
            Using acTr As Transaction = acDoc.TransactionManager.StartTransaction
                Dim acBlkTbl As BlockTable = acTr.GetObject(acDB.BlockTableId, OpenMode.ForRead)
                Dim acBlkTblRec As BlockTableRecord = acTr.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
                For Each Obj As SelectedObject In selResult.Value   ' loop thru each 3dsolid
                  Dim eee As Entity = acTr.GetObject(Obj.ObjectId, OpenMode.ForRead)
                  Dim objWork As Solid3d = acTr.GetObject(Obj.ObjectId, OpenMode.ForWrite) '.Clone
                  If objWork.MassProperties.Volume = 0 Then
                        Continue For
                  End If
                  Dim brep As New BoundaryRepresentation.Brep(objWork)
                  Dim EXT As BoundBlock3d = brep.BoundBlock
                  If EXT.Direction1.Length = EXT.Direction2.Length Then
                        If PipeODs.ContainsKey(EXT.Direction1.Length.ToString) Then
                            Dim pipeod As Double = EXT.Direction1.Length
                            Dim pipelength As Double = EXT.Direction3.Length
                            'pa.Pipes.Add(New Pipe(pipeod, pipelength, Obj.ObjectId))
                            objWork.Color = Autodesk.AutoCAD.Colors.Color.FromColor(System.Drawing.Color.White)
                        End If
                  End If
                Next
            End Using
      End Using


" Dim EXT As boundblock 3d = brep。BoundBlock”和下面的If/Then是(我假设)魔术需要发生的地方。我只是不理解旋转矩阵和坐标系矩阵,所以这超出了我的理解范围。
我希望这是足够的信息。如果有人能帮我,我将不胜感激。
谢谢!!

**** Hidden Message *****

gile 发表于 2020-4-7 11:51:40

嗨,这似乎有效:    public static bool TryGetPipe(solid 3d solid,out Pipe)。
{。
pipe =新管道();。
使用(var brep = new Brep(solid))。
{。
//必须有4条边。
var edges = brep,边缘;。
如果(边缘,Count()!= 4)。
返回false。

//所有的eges必须是圆形或椭圆形的。
var曲线=边,select(e = >((external Curve 3d)e . Curve),native curve);。
如果(!曲线,All(c => c为圆弧3d

Michael2 发表于 2020-4-8 16:09:40

c为椭圆3d))。
返回false。

//必须有两个不同的中心。
var centers = curves。
,Select(c => c是CircularArc3d?((CircularArc3d)c),中心:((EllipticalArc3d)c)。居中)。
,Distinct()。
,to array();。
如果(居中,长度!= 2)。
返回false。

//必须有两个不同的半径。
变化半径=曲线。
,Select(c => c是CircularArc3d?((CircularArc3d)c),半径:((椭圆率3d)c)。MinorRadius)。
,distinct(new double comparer())。
,to array();。
if(半径,长度!= 2)。
返回false。

pipe = new Pipe()。
{。
直径=数学,Max(半径,半径) * 2.0,。
方向=中心,GetVectorTo(centers),GetNormal(),。
长度=中心,DistanceTo(centers),。
厚度=数学,Abs(半径 -半径)。
};。
返回true。
}。
}。

结构管道。
{。
公共双直径{ get设置;}。
public vector 3d Direction { get;设置;}。
public double Length { get设置;}。
public double Thickness { get设置;}。
}。

class double comparer:iequalitycomprer。
{。
public bool Equals(double x,double y) =>。
数学,Round(x,9) ==数学。Round(x,9);。
public int get hashcode(double d)= > Math,圆形(d,9)。get hashcode();。
}测试命令:   。
公共静态void测试()。
{。
var doc =应用,document manager . MdiActiveDocument;。
var db = doc,数据库;。
var ed = doc,编辑;。
var options = new promptentity options(" \ n选择实体3d:");。
选项,SetRejectMessage(" \ n所选对象不是solid3d,");。
选项,AddAllowedClass(typeof(Solid3d),true);。
变量结果= ed,GetEntity(选项);。
if(结果,地位!=提示状态,好)。
返回;。
使用(var tr = db,transaction manager . start transaction())。
{。
var solid = (Solid3d)tr,GetObject(结果,ObjectId,OpenMode。for read);。
if (TryGetPipe(实体,外部管道管道))。
{。
ed,WriteMessage(。
$ " \长度:{pipe,长度}" +。
$ " \仪表:{管道,直径}" +。
$ " \厚度:{管道,厚度}" +。
$ " \方向:{管道,方向}”);。
}。
trcommit();。
}。
}。

gile 发表于 2020-4-8 17:07:32

非常感谢你的回复。我很抱歉花了这么长时间才回复你。
你的代码大部分工作,但是我怀疑“长度”不会按照我需要的方式计算,所以我做了第三个示例管道(附加)。
我期望尝试弄清楚如何获得2条曲线之间的最大距离(因为这将是切割管道所需的管道长度),而不是从中心到中心的距离。
但是当我在此示例上运行该函数时,它在中心返回了 4 个元素,因此它不会被视为 Pipe。奇怪的是,其中2个元素彼此相同,另外2个元素彼此相同......数组似乎不是不同的。
这可能是一个四舍五入的问题吗?

MickD 发表于 2020-4-8 19:03:03

像这样尝试(您可以在DoubleComparer和PointComparer中存储值以满足您的需要)
静态bool-TryGetPipe(Solid3d-solid,out-Pipe)
{
管道=新管道()
使用(var-brep=new-brep(solid))
{
//必须有4条边。
var-edges=brep.edges
如果(edges.Count()!=4)
返回false
//所有EGE必须为圆形或椭圆形。
var外部曲线=边。选择(e=>(外部曲线3d)e.Curve)
如果(!externalCurves.All(c=>c.iscircularc

Michael2 发表于 2020-4-9 14:10:40

c.IsEllipticalArc))
返回false
var nativeCurves=外部曲线。选择(c=>c.NativeCurve).ToArray()
//必须有两个不同的中心。
var:pointComparer=new:pointComparer()
风险中心=本地曲线
。选择(c=>c是循环C3d?((循环C3d)c)。中心:((EllipticalArc3d)c.中心)
.Distinct(指针比较器)
.ToArray()
如果(centers.Length!=2)
返回false
双倍长度=中心。距离(中心)
//必须有两个不同的半径
var doublecomper=新的DoubleComparer()
var radii=nativeCurves
。选择(c=>c是循环C3d?((循环C3d)c)。半径:((EllipticalArc3d)c.米诺拉迪厄斯)
.Distinct(双压缩)
.ToArray()
如果(半径长度!=2)
返回false
双半径=数学。最大值(半径,半径)
foreach(本地曲线中的var组
<div>类型<EllipticalArc3d>(</div>)
。GroupBy(e=>e.Center,pointComparer))
{
double-majRad=组。最大值(e=>e.MajorRadius)
长度+=数学。Sqrt(majRad*Majrada-半径*radius)
}
管道=新管道()
{
直径=半径*2.0,
方向=中心。GetVectorTo(中心)。GetNormal(),
长度=长度,
厚度=数学。Abs(半径-半径)
}
返回true
}
}
结构管道
{
公共双直径{get;set;}
公共矢量三维方向{get;set;}
公共双倍长度{get;set;}
公共双厚度{get;set;}
}
类双重比较器:IEqualityComparer
{
公共布尔等于(双x,双y)=>
数学。四舍五入(x,9)=数学。圆形(x,9)
公共int-GetHashCode(双d)=>Math。四舍五入(d,9).GetHashCode()
}
类指针比较器:IEqualityComparer
{
公共布尔等于(Point3d x,Point3d y)=>
x。IsEqualTo(y,新公差(1e-10,1e-9))
公共int-GetHashCode(Point3d-p)=>
新的Point3d(Math.Round(p.X,9),Math.Round(p.Y,9),Math.Rourn(p.Z,9)).GetHashCode()
}

Michael2 发表于 2020-4-9 15:44:33

如果你能管的中心行哟

gile 发表于 2020-4-9 15:57:08

非常感谢吉尔。这似乎工作。
页: [1]
查看完整版本: 我想确定管几何可以我