//判断一个特征中的面,与指定面在AAG图中是否存在链接 private bool FeatureConncetFace(MyNewDefineFeature feature, Tag faceNode) { //找到tag,指定的Facenode GripchFaceNode tempFaceNode; int index1 = 0; for (int i = 0; i < NumOfFace; i++) { if (FaceNodeList[i].FaceTag == faceNode) { tempFaceNode = FaceNodeList[i]; index1 = i; } } //判断feature中的面与指定的面之间是否存在关联 foreach (GripchFaceNode face2 in feature.MyNewFeature) { int index2 = 0; for (int j = 0; j < NumOfFace; j++) { if (FaceNodeList[j] == face2) { index2 = j; } } if (adjmatrix[index1, index2] != null) { return(true); } } return(false); }
//判断两个特征是否同轴, public static bool FeatureIsConcentric(MyNewDefineFeature Feature1, MyNewDefineFeature Feature2) { GripchFaceNode FaceNode1 = GetCylinderOrConFaceNode(Feature1); GripchFaceNode FaceNode2 = GetCylinderOrConFaceNode(Feature2); int Is_equal; Program.theUfVec3.IsParallel(FaceNode1.Face_Axis, FaceNode2.Face_Axis, 0, out Is_equal); if (Is_equal == 1) { //获得轴线上两点的连线适量 double [] Point1_to_Point2 = { 0.0, 0.0, 0.0 }; Point1_to_Point2[0] = FaceNode1.Face_Axis_Point[0] - FaceNode2.Face_Axis_Point[0]; Point1_to_Point2[1] = FaceNode1.Face_Axis_Point[1] - FaceNode2.Face_Axis_Point[1]; Point1_to_Point2[2] = FaceNode1.Face_Axis_Point[2] - FaceNode2.Face_Axis_Point[2]; int is_parallel; Program.theUfVec3.IsParallel(Point1_to_Point2, FaceNode1.Face_Axis, 1, out is_parallel); if (is_parallel == 1)//矢量平行 { return(true); } } return(false); }
//得到特征中的点 public static void GetVertexOfFeature(MyNewDefineFeature Feature, out HashSet <Point3d> Verter_List) { Verter_List = new HashSet <Point3d>(); Tag[] EdgeList; int VertexNum; double[] point1 = { 0.0, 0.0, 0.0 }, point2 = { 0.0, 0.0, 0.0 }; for (int i = 0; i < Feature.FaceNumber; i++) { ufmodel.AskFaceEdges(Feature.MyNewFeature[i].FaceTag, out EdgeList); foreach (Tag EdgeTag in EdgeList) { ufmodel.AskEdgeVerts(EdgeTag, point1, point2, out VertexNum); //顶点坐标需要四舍五入,否则可能导致同一个点计算出两个点 Point3d Point1 = new Point3d(Math.Round(point1[0], 2), Math.Round(point1[1], 2), Math.Round(point1[2], 2)); Point3d Point2 = new Point3d(Math.Round(point2[0], 2), Math.Round(point2[1], 2), Math.Round(point2[2], 2)); switch (VertexNum) { case 1: Verter_List.Add(Point1); break; case 2: Verter_List.Add(Point1); Verter_List.Add(Point2); break; default: break; } } } }
//将两个特征进行组合成一个特征,把两个特征组合成一个特征主要是把两个特征的面组合到一起 public static void AssociationFeature(MyNewDefineFeature Feature1, MyNewDefineFeature Feature2) { for (int i = 0; i < Feature2.FaceNumber; i++) { Feature1.AddFaceNode(Feature2.MyNewFeature[i]);//把Feature2中的特征面保存到Feature1中,进行特征的组合 } }
//判断一个特征是否为一个盲孔 public static bool IsCounterboreHole(MyNewDefineFeature Feature1) { //单独的盲孔,边数为3的盲孔是存在阶梯孔的情况 if (Feature1.FaceNumber == 2 && (Feature1.EdgeNumber >= 2) && Feature1.VertexNumber == 0) { //先计算两面之间的夹角 double Angle; MyFace.AskAngleOfFace(Feature1.MyNewFeature[0].FaceTag, Feature1.MyNewFeature[1].FaceTag, out Angle); if (Angle != 90.0) { return(false); } if (Feature1.MyNewFeature[0].NodeFaceType == MyNewFaceType.Cylindrical && Feature1.MyNewFeature[1].NodeFaceType == MyNewFaceType.Planar) { //判断盲孔:一个面为凹圆柱面,一个面为平面,且两面的交线为凹边 Tag[] SharedEdges; Program.theUfmodel.AskSharedEdges(Feature1.MyNewFeature[0].FaceTag, Feature1.MyNewFeature[1].FaceTag, out SharedEdges); if (MyEdges.IsConcaveEdge(SharedEdges[0]) && (MyFace.IsConcaveFace(Feature1.MyNewFeature[0].FaceTag) == 2)) { return(true); } } else if (Feature1.MyNewFeature[1].NodeFaceType == MyNewFaceType.Cylindrical && Feature1.MyNewFeature[0].NodeFaceType == MyNewFaceType.Planar) { //判断盲孔:一个面为凹圆柱面,一个面为平面,且两面的交线为凹边 Tag[] SharedEdges; Program.theUfmodel.AskSharedEdges(Feature1.MyNewFeature[0].FaceTag, Feature1.MyNewFeature[1].FaceTag, out SharedEdges); if (MyEdges.IsConcaveEdge(SharedEdges[0]) && (MyFace.IsConcaveFace(Feature1.MyNewFeature[1].FaceTag) == 2)) { return(true); } } } return(false); }
//构建特征中Face的角度属性邻接图 public AngleGraph(MyNewDefineFeature Feature1) { int FaceNum = Feature1.FaceNumber; NumOfFace = FaceNum;//记录图中面的个数 //初始化邻接矩阵和顶点数组 adjmatrix = new double[FaceNum, FaceNum]; Tag[] shared_edges; double FaceAngle; //将代表邻接矩阵的表全初始化为0 for (int i = 0; i < FaceNum; i++) { for (int j = 0; j < FaceNum; j++) { if (i == j) { adjmatrix[i, j] = 0; continue; } //判断两个面是否相邻 ufmodel.AskSharedEdges(Feature1.MyNewFeature[i].FaceTag, Feature1.MyNewFeature[j].FaceTag, out shared_edges); if (shared_edges.Length == 0)//不相邻的情况取-1 { adjmatrix[i, j] = -1.0; } else { MyFace.AskAngleOfFace(Feature1.MyNewFeature[i].FaceTag, Feature1.MyNewFeature[j].FaceTag, out FaceAngle); adjmatrix[i, j] = Math.Round(FaceAngle, 2);//四舍五入,保留2位小数 } } } }
//识别特征链表中特征的类型 public void FeatureListType() { for (int i = 0; i < SubFeaturesList.Count; i++) { SubFeaturesList[i].FeatureType = MyNewDefineFeature.GetFeatureType(SubFeaturesList[i]); } }
//判断特征是否是一个矩形腔 public static bool IsRectCavity(MyNewDefineFeature Feature1) { bool IsRect_Through_solt = false; if (Feature1.FaceNumber == 5 && Feature1.EdgeNumber == 12 && Feature1.VertexNumber == 8) { for (int i = 0; i < 5; i++) { //三个面都要是平面 if (Feature1.MyNewFeature[i].NodeFaceType != MyNewFaceType.Planar) { return(false); } } //面之间要两两垂直 for (int index1 = 0; index1 < 3; index1++) { for (int index2 = index1 + 1; index2 < 3; ++index2) { double tmp = Feature1.FeatureFaceAngleGraphic.adjmatrix[index1, index2]; if (tmp != -1)//相邻,其实还要判断夹角是否相等 { if (tmp != 90.0) { return(false); } } } } IsRect_Through_solt = true; } return(IsRect_Through_solt); }
//判断特征是否为一个孤立的光顺面 public static bool IsIsolatedSmoothSurface(MyNewDefineFeature Feature1) { if (Feature1.FaceNumber == 1 && Feature1.MyNewFeature[0].NodeFaceType == MyNewFaceType.Planar) { return(true); } return(false); }
//得到图的连通子图,并存储特征 public void GetSubConnectGraph() { List <MyNewDefineFeature> TempFeatureList = new List <MyNewDefineFeature>(); for (int i = 0; i < NumOfFace; i++)//遍历面节点的List { bool IsExit = false; foreach (MyNewDefineFeature feature in TempFeatureList) { //如果特征中包含了这个面,就继续下一个面的判断 if (feature.Contains(FaceNodeList[i].FaceTag)) { IsExit = true; break; } else //在feature这个特征中不包含面FaceNodeList[i]时,需要判断feature中的特征面与FaceNodeList[i]这个面是否有链接 { if (FeatureConncetFace(feature, FaceNodeList[i].FaceTag))//如果特征面与指定面之间存在链接的边则,包含进该边 { feature.AddFaceNode(FaceNodeList[i]); IsExit = true; break; } } } //遍历完所有特征,后发现该面并没有被包含,则为该面定义一个新的特征 if (!IsExit) { MyNewDefineFeature temFeature = new MyNewDefineFeature(); temFeature.AddFaceNode(FaceNodeList[i]); TempFeatureList.Add(temFeature); } } //在判断特征之间是否有两两连接的关系 for (int i = 0; i < TempFeatureList.Count; i++) { for (int j = i + 1; j < TempFeatureList.Count; j++) { foreach (GripchFaceNode Facenode in TempFeatureList[j].MyNewFeature) { if (FeatureConncetFace(TempFeatureList[i], Facenode.FaceTag))//如果一个特征中的面与另一个特征中的面有链接,则合并两个特征 { for (int k = 0; k < TempFeatureList[j].FaceNumber; k++) { TempFeatureList[i].AddFaceNode(TempFeatureList[j].MyNewFeature[k]); } //SubFeaturesList[j] = null; TempFeatureList.RemoveAt(j); } } } } SubFeaturesList = TempFeatureList; }
//判断是否是一个锥孔 public static bool IsConicalHole(MyNewDefineFeature Feature1) { if (Feature1.FaceNumber == 1 && Feature1.MyNewFeature[0].NodeFaceType == MyNewFaceType.Conical) { int temp = MyFace.IsConcaveFace(Feature1.MyNewFeature[0].FaceTag); if (temp == 2)//同时需要判断该圆柱面为内圆柱面 { return(true); } } return(false); }
//判断是否为圆柱凸台 public static bool IsOutterCylinderSurface(MyNewDefineFeature Feature1) { if (Feature1.FaceNumber == 1 && Feature1.MyNewFeature[0].NodeFaceType == MyNewFaceType.Cylindrical) { int temp = MyFace.IsConcaveFace(Feature1.MyNewFeature[0].FaceTag); if (temp == 1)//同时需要判断该圆柱面为外圆柱面 { return(true); } } return(false); }
//目前只针对有圆柱面和圆锥面的特征进行组合 public static bool FeatureIsContainCylOrCon(MyNewDefineFeature Feature1) { for (int i = 0; i < Feature1.FaceNumber; i++) { if (Feature1.MyNewFeature[i].NodeFaceType == MyNewFaceType.Cylindrical || Feature1.MyNewFeature[i].NodeFaceType == MyNewFaceType.Conical) { return(true); } } return(false); }
//得到一个特征中边的个数 public static void GetEdgeOfFeature(MyNewDefineFeature Feature, out HashSet <Tag> Edge_Feature) { Edge_Feature = new HashSet <Tag>(); Tag[] EdgeList; for (int i = 0; i < Feature.FaceNumber; i++) { Program.theUfmodel.AskFaceEdges(Feature.MyNewFeature[i].FaceTag, out EdgeList); foreach (Tag EdgeTag in EdgeList) { Edge_Feature.Add(EdgeTag); } } }
//从众多的子图特征中选择余图特征 private MyNewDefineFeature GetMaxSubGraphic(List <MyNewDefineFeature> SubFeaturesList) { MyNewDefineFeature MaxSubGrphicFeature = SubFeaturesList[0]; for (int i = 1; i < SubFeaturesList.Count; i++) { if (SubFeaturesList[i].FaceNumber > MaxSubGrphicFeature.FaceNumber) { MaxSubGrphicFeature = SubFeaturesList[i]; } } return(MaxSubGrphicFeature); }
//判断特征类型 public static NewSelfDefFeatureType GetFeatureType(MyNewDefineFeature Feature1) { NewSelfDefFeatureType FeatureType = NewSelfDefFeatureType.OTHER_TYPE; HashSet <Tag> Edge_Feature; HashSet <Point3d> Vertex_Feature; MyNewEdge.GetEdgeOfFeature(Feature1, out Edge_Feature); MyVertex.GetVertexOfFeature(Feature1, out Vertex_Feature); Feature1.EdgeNumber = Edge_Feature.Count; //特征中边的数目 Feature1.VertexNumber = Vertex_Feature.Count; //特征中顶点的数目; Feature1.FeatureFaceAngleGraphic = new AngleGraph(Feature1); //构建特征中面之间的夹角图 //先识别出每个孤立特征的特征类型,然后在进行组合 if (IsThroughHole(Feature1)) //通孔 { FeatureType = NewSelfDefFeatureType.ThroughHole; for (int i = 0; i < Feature1.FeatureAdjacentFaceList.Count; i++) { if (Feature1.FeatureAdjacentFaceList[i].FaceType == MyNewFaceType.Cylindrical) { FeatureType = NewSelfDefFeatureType.HORIZONTAL_HOLE;//横孔 } } } else if (IsRECT_THROUGH_SOLT(Feature1))//矩形通腔 { FeatureType = NewSelfDefFeatureType.RECT_THROUGH_SOLT; } else if (IsCounterboreHole(Feature1))//盲孔 { FeatureType = NewSelfDefFeatureType.BlindHole; } else if (IsConicalHole(Feature1))//锥孔 { FeatureType = NewSelfDefFeatureType.Conical_HOLE; } else if (IsIsolatedSmoothSurface(Feature1)) { FeatureType = NewSelfDefFeatureType.ISOLATED_SMOOTH_SURFACE; //孤立的光顺面; } else if (IsRectCavity(Feature1)) //判断是否是矩形腔 { FeatureType = NewSelfDefFeatureType.RECT_CAVITY; //矩形腔 } else if (IsOutterCylinderSurface(Feature1)) { FeatureType = NewSelfDefFeatureType.Outter_Cylinder_Surface;//凸台特征的外圆柱面 } return(FeatureType); }
//得到一个特征中的圆柱面或圆锥面 public static GripchFaceNode GetCylinderOrConFaceNode(MyNewDefineFeature Feature1) { GripchFaceNode FaceNode = null; for (int i = 0; i < Feature1.FaceNumber; i++) { if (Feature1.MyNewFeature[i].NodeFaceType == MyNewFaceType.Conical || Feature1.MyNewFeature[i].NodeFaceType == MyNewFaceType.Cylindrical) { FaceNode = Feature1.MyNewFeature[i]; } } return(FaceNode); }
//判断两个特征是否相邻 public static bool FeatureIsAdjacent(MyNewDefineFeature Feature1, MyNewDefineFeature Feature2) { Tag[] SharedEdge; for (int i = 0; i < Feature1.FaceNumber; i++) { for (int j = 0; j < Feature2.FaceNumber; j++) { Program.theUfmodel.AskSharedEdges(Feature1.MyNewFeature[i].FaceTag, Feature2.MyNewFeature[j].FaceTag, out SharedEdge); if (SharedEdge.Length > 0)//表示两个特征之间存在相邻的边,及特征相邻 { return(true); } } } return(false); }
//分解特征AAG(属性邻接图)得到子图 public void GetAllSubFeature() { //1、删除分解基面中内环边 for (int i = 0; i < DeCompseBaseFaceList.Count; ++i) { int InnerLoopEdgesNum; ////分解基面为凸面时才删除内环边 //if (!MyNewFace.IsConCavityFacebyEdge(DeCompseBaseFaceList[i])) //{ // //找到内环边数组,并删除边连接 //面中内环边的个数 InnerLoopEdgesNum = GetInnerLoopEdgesNum(DeCompseBaseFaceList[i]); Tag InnerEdgeTag; for (int j = 0; j < InnerLoopEdgesNum; j++) { //找到一条分解基面内环边, InnerEdgeTag = GetEdgeTagInInnerLoop(DeCompseBaseFaceList[i], j); //在图中删除该边 //1、首先在图中找到该边节点,并设置该节点值为空 FoundAndDeletEdgeNode(InnerEdgeTag); // //删除内环后,包含该边的面的内环边链表中也要相应的减去该边 // Tag[] FaceList; // Program.theUfmodel.AskEdgeFaces(InnerEdgeTag, out FaceList); // // for(int m=0;m<FaceList.Length;m++) // for (int n = 0; n < NumOfFace; n++) // { // if (FaceNodeList[n].FaceTag == FaceList[m]) // { // FaceNodeList[n].FaceInnerLoopEdges.Remove(InnerEdgeTag); // } // } } //} } //在进行第2步之前,需要先识别出连通子图,并存储为特征子图 GetSubConnectGraph(); //余图:目前暂定义为面结点最多的特征 MyNewDefineFeature SubMaxFeatureGraphic = GetMaxSubGraphic(SubFeaturesList); List <Tag> YuFaceList = new List <Tag>(); for (int i = 0; i < SubMaxFeatureGraphic.FaceNumber; i++) { YuFaceList.Add(SubMaxFeatureGraphic.MyNewFeature[i].FaceTag); } //构建余图 FeatureGraphic YuGraphic1 = new FeatureGraphic(YuFaceList); //2、遍历余图,保留凹面之间的连接,删除凹凸面之间的连接 for (int i = 0; i < YuGraphic1.NumOfFace; ++i) { if (YuGraphic1.FaceNodeList[i].IsConCavityFace /*&& YuGraphic1.FaceNodeList[i].FaceInnerLoopEdges.Count==0*/)//如果这个面是凹面,还要确定这条导致该面为凹面的边是否存在,如果不存在则该面为凸面 { Tag[] AdjacentFaces; Program.theUfmodel.AskAdjacFaces(YuGraphic1.FaceNodeList[i].FaceTag, out AdjacentFaces); //判断哪些邻面是凸面; for (int j = 0; j < AdjacentFaces.Length; j++) { if (IsConvexFace(AdjacentFaces[j]))//如果是凸面 { Tag[] SharedEdge; Program.theUfmodel.AskSharedEdges(YuGraphic1.FaceNodeList[i].FaceTag, AdjacentFaces[j], out SharedEdge); for (int k = 0; k < SharedEdge.Length; ++k) { FoundAndDeletEdgeNode(SharedEdge[k]); } } } } } //在进行第3步之前,需要先识别出连通子图,并存储为特征子图 GetSubConnectGraph(); //划分完特征后,就可以确定邻接面的信息 GetFeatureListAdjacentFace(); //进行第三步前,需要存储识别出来的连通子图,并存储为特征子图, //对余图进行余下操作 //对面的方程和法失相同的部分计算留到后面有时间在考虑 }
//根据得到的Sub特征链表,进行组合,并存储进SubFeaturesList public void AssembleFeature() { //默认SubFeatureList[0]中存储的零件的毛坯面特征 for (int i = 0; i < SubFeaturesList.Count; i++) { for (int j = 0; j < SubFeaturesList.Count; j++) { if (i == j || SubFeaturesList[i].FeatureType == NewSelfDefFeatureType.OTHER_TYPE || SubFeaturesList[j].FeatureType == NewSelfDefFeatureType.OTHER_TYPE) { continue; } //判断两个特征是否相邻 if (MyNewDefineFeature.FeatureIsAdjacent(SubFeaturesList[i], SubFeaturesList[j])) { //两个特征都含有圆柱或圆锥面 if (MyNewDefineFeature.FeatureIsContainCylOrCon(SubFeaturesList[i]) && MyNewDefineFeature.FeatureIsContainCylOrCon(SubFeaturesList[j])) { if (MyNewDefineFeature.FeatureIsConcentric(SubFeaturesList[i], SubFeaturesList[j]))//如果两个特征同轴 { MyNewDefineFeature.AssociationFeature(SubFeaturesList[i], SubFeaturesList[j]); if (SubFeaturesList[i].FeatureType == NewSelfDefFeatureType.ThroughHole && SubFeaturesList[j].FeatureType == NewSelfDefFeatureType.BlindHole) { SubFeaturesList[i].FeatureType = NewSelfDefFeatureType.PLANAR_COUNTERBORE_HOLE;//平头沉头孔 } else if (SubFeaturesList[i].FeatureType == NewSelfDefFeatureType.BlindHole && SubFeaturesList[j].FeatureType == NewSelfDefFeatureType.ThroughHole) { SubFeaturesList[i].FeatureType = NewSelfDefFeatureType.PLANAR_COUNTERBORE_HOLE;//平头沉头孔 } else if (SubFeaturesList[i].FeatureType == NewSelfDefFeatureType.BlindHole && SubFeaturesList[j].FeatureType == NewSelfDefFeatureType.Conical_HOLE) { SubFeaturesList[i].FeatureType = NewSelfDefFeatureType.CONICAL_COUNTERBORE_HOLE;//锥头沉头孔 } else if (SubFeaturesList[i].FeatureType == NewSelfDefFeatureType.Conical_HOLE && SubFeaturesList[j].FeatureType == NewSelfDefFeatureType.BlindHole) { SubFeaturesList[i].FeatureType = NewSelfDefFeatureType.CONICAL_COUNTERBORE_HOLE;//锥头沉头孔 } else if (SubFeaturesList[i].FeatureType == NewSelfDefFeatureType.ThroughHole && SubFeaturesList[j].FeatureType == NewSelfDefFeatureType.Conical_HOLE) { SubFeaturesList[i].FeatureType = NewSelfDefFeatureType.CONICAL_COUNTERBORE_HOLE;//锥头沉头孔 } else if (SubFeaturesList[i].FeatureType == NewSelfDefFeatureType.Conical_HOLE && SubFeaturesList[j].FeatureType == NewSelfDefFeatureType.ThroughHole) { SubFeaturesList[i].FeatureType = NewSelfDefFeatureType.CONICAL_COUNTERBORE_HOLE;//锥头沉头孔 } else if (SubFeaturesList[i].FeatureType == NewSelfDefFeatureType.BlindHole && SubFeaturesList[j].FeatureType == NewSelfDefFeatureType.BlindHole) { SubFeaturesList[i].FeatureType = NewSelfDefFeatureType.PLANAR_COUNTERBORE_HOLE;//平头沉头孔 } } } else if (SubFeaturesList[i].FeatureType == NewSelfDefFeatureType.Conical_HOLE && SubFeaturesList[j].FeatureType == NewSelfDefFeatureType.ISOLATED_SMOOTH_SURFACE) { MyNewDefineFeature.AssociationFeature(SubFeaturesList[i], SubFeaturesList[j]); SubFeaturesList[i].FeatureType = NewSelfDefFeatureType.PIN_HOLE;//锥头沉头孔 } else if (SubFeaturesList[i].FeatureType == NewSelfDefFeatureType.ISOLATED_SMOOTH_SURFACE && SubFeaturesList[j].FeatureType == NewSelfDefFeatureType.Conical_HOLE) { MyNewDefineFeature.AssociationFeature(SubFeaturesList[i], SubFeaturesList[j]); SubFeaturesList[i].FeatureType = NewSelfDefFeatureType.PIN_HOLE;//锥头沉头孔 } SubFeaturesList.RemoveAt(j);//如果两个特征相邻,才移除 } } } }