/// <summary> /// 三角形要素メッシュを作成する(DelFEM版) /// 2次三角形/1次三角形共用ルーチン /// </summary> /// <param name="order">三角形要素の補間次数</param> /// <param name="EditCad2D">Cadオブジェクト</param> /// <param name="LoopList">ループリスト</param> /// <param name="EdgeCollectionList">ポート境界辺のコレクションのリスト</param> /// <param name="Mesher2D">メッシュ生成装置</param> /// <param name="doubleCoords">[OUT]座標リスト(このリストのインデックス+1が節点番号として扱われます)</param> /// <param name="elements">[OUT]要素データリスト 要素データはint[] = { 要素番号, 媒質インデックス, 節点番号1, 節点番号2, ...}</param> /// <param name="portList">[OUT]ポート節点リストのリスト</param> /// <param name="forceBCNodeNumbers">強制境界節点配列</param> /// <returns></returns> public static bool MkTriMesh( int order, CCadObj2D EditCad2D, IList<CadLogic.Loop> LoopList, IList<EdgeCollection> EdgeCollectionList, ref CMesher2D Mesher2D, out IList<double[]> doubleCoords, out IList<int[]> elements, out IList<IList<int>> portList, out int[] forceBCNodeNumbers) { elements = new List<int[]>(); // 要素リスト doubleCoords = new List<double[]>(); forceBCNodeNumbers = null; portList = new List<IList<int>>(); if (LoopList.Count == 0) { return false; } Dictionary<int, bool> forceBCNodeNumberDic = new Dictionary<int, bool>(); int nodeCounter = 0; // 節点番号カウンター int elementCounter = 0; // 要素番号カウンター // ポート境界 //int portCounter = 0; // 番号でソートする(ポート番号順になっていることを保証する) ((List<EdgeCollection>)EdgeCollectionList).Sort(); /////////////////////////////////////////////////////// // FEMメッシュの作成 if (Mesher2D != null) { Mesher2D.Clear(); Mesher2D.Dispose(); Mesher2D = null; } //1つの 要素の長さ double elementLength = Constants.MesherElementLength; // メッシャーを生成する Mesher2D = new CMesher2D(EditCad2D, elementLength); // メッシュの座標リスト 最初の数点はCadの頂点、その後メッシュ切りで生成された座標が格納される IList<CVector2D> coords = Mesher2D.GetVectorAry(); // 頂点アレイのリスト: Cadの頂点に対応 IList<SVertex> vertexAry = Mesher2D.GetVertexAry(); // 線分アレイのリスト: Cadの辺に対応 IList<CBarAry> barArySet = Mesher2D.GetBarArySet(); // 三角形アレイのリスト: Cadの面(ループ)に対応 IList<CTriAry2D> triArySet = Mesher2D.GetTriArySet(); //printMesher2D(mesher2d); int coordIndexBase = coords.Count; nodeCounter = coords.Count; // 辺ID→エッジコレクションのリストインデックス変換マップ Dictionary<uint, int> eIdCadToEdgeCollectionIndex = new Dictionary<uint, int>(); for (int i = 0; i < EdgeCollectionList.Count; i++) { EdgeCollection edgeCollection = EdgeCollectionList[i]; foreach (uint eIdCad in edgeCollection.EdgeIds) { if (!eIdCadToEdgeCollectionIndex.ContainsKey(eIdCad)) { eIdCadToEdgeCollectionIndex.Add(eIdCad, i); } } } // メッシュ辺の頂点ペア→ バーアレイのバー 変換マップ // key: "辺の頂点インデックス1_頂点インデックス2" value: int[2] value[0]: バーアレイのインデックス value[1]:バーアレイ内バーのリストインデックス Dictionary<string, int[]> edgeToBarIndexes = new Dictionary<string, int[]>(); // メッシュの辺の頂点ペア → 辺の中点の頂点ID // Noye: 1次要素の場合、中点は作成しないが、辺のハッシュとしてedgeToMiddlePtVertexIdを流用している Dictionary<string, uint> edgeToMiddlePtVertexId = new Dictionary<string, uint>(); // 使用した頂点IDのマップ IList<uint> usedVertexIds = new List<uint>(); // 節点番号付与 // 2次三角形要素:メッシュの辺の中点を追加する // 要素データ作成 elementCounter = 0; foreach (CTriAry2D triAry in triArySet) { // 三角形アレイのID uint id_triAry = triAry.id; // CadループID uint id_l_cad = triAry.id_l_cad; // 媒質インデックス int mediaIndex = 0; // 媒質インデックスの取得 CadLogic.Loop loop = CadLogic.getLoop(LoopList, id_l_cad); mediaIndex = loop.MediaIndex; if (mediaIndex == CadLogic.MetalMediaIndex) { // 導体の場合、要素を作成しない continue; } // 節点番号は、頂点IDで割り振って、一連の処理を行う // ただし、領域に導体があった場合、歯抜けが存在することになるので全処理完了後に調整する foreach (STri2D tri in triAry.m_aTri) { // 節点番号 int[] nodeNumbers = null; if (order == Constants.FirstOrder) { // 1次三角形要素 nodeNumbers = new int[] { (int)tri.v[0] + 1, (int)tri.v[1] + 1, (int)tri.v[2] + 1, }; // 中点は作成しないが、辺のハッシュは必要 for (int i = 0; i < 3; i++) { // (v1, v2)は節点3:(節点0, 節点1) 節点4:(節点1, 節点2) 節点5:(節点2, 節点0)に対応 // tri.vは頂点インデックスが格納されているので頂点IDにするために+1している uint v1 = tri.v[i] + 1; uint v2 = tri.v[(i + 1) % 3] + 1; string vertexIdsKey = (v2 >= v1) ? string.Format("{0}_{1}", v1, v2) : string.Format("{0}_{1}", v2, v1); if (edgeToMiddlePtVertexId.ContainsKey(vertexIdsKey)) { // 登録済み } else { // 存在しない場合は、辺のキーを登録 uint dummy_vMiddle = 0; edgeToMiddlePtVertexId.Add(vertexIdsKey, dummy_vMiddle); } } } else { // 2次三角形要素 nodeNumbers = new int[] { (int)tri.v[0] + 1, (int)tri.v[1] + 1, (int)tri.v[2] + 1, 0, 0, 0 }; // 中点作成 // 中点の節点番号を探す for (int i = 0; i < 3; i++) { // (v1, v2)は節点3:(節点0, 節点1) 節点4:(節点1, 節点2) 節点5:(節点2, 節点0)に対応 // tri.vは頂点インデックスが格納されているので頂点IDにするために+1している uint v1 = tri.v[i] + 1; uint v2 = tri.v[(i + 1) % 3] + 1; string vertexIdsKey = (v2 >= v1) ? string.Format("{0}_{1}", v1, v2) : string.Format("{0}_{1}", v2, v1); // 中点の頂点ID uint vMiddle = 0; // 中点を作成済みかマップを検査 if (edgeToMiddlePtVertexId.ContainsKey(vertexIdsKey)) { vMiddle = edgeToMiddlePtVertexId[vertexIdsKey]; } else { // 存在しない場合は、中点を作成する // 始点、終点の取得 CVector2D[] pts = new CVector2D[] { coords[(int)v1 - 1], coords[(int)v2 - 1] }; // 頂点ID - 1に注意 // 中点を追加 CVector2D mpt = new CVector2D((pts[0].x + pts[1].x) * 0.5, (pts[0].y + pts[1].y) * 0.5); coords.Add(mpt); nodeCounter++; // 中点の頂点ID vMiddle = (uint)coords.Count; // 中点の頂点IDをマップに追加 edgeToMiddlePtVertexId.Add(vertexIdsKey, vMiddle); } System.Diagnostics.Debug.Assert(vMiddle != 0); // 中点3, 4, 5の節点の節点番号を格納 nodeNumbers[i + 3] = (int)vMiddle; } } // 要素番号 int elementNo = elementCounter + 1; // 要素 int[] elementData = new int[2 + nodeNumbers.Length]; elementData[0] = elementNo; elementData[1] = mediaIndex; for (int ino = 0; ino < nodeNumbers.Length; ino++) { elementData[2 + ino] = nodeNumbers[ino]; } elements.Add(elementData); // 使用した頂点IDをリストに追加 foreach (int nodeNumber in nodeNumbers) { uint vId = (uint)nodeNumber; if (usedVertexIds.IndexOf(vId) == -1) // 未追加なら追加する { usedVertexIds.Add(vId); } } // 要素カウンタを進める elementCounter++; } } System.Diagnostics.Debug.Assert(elementCounter == elements.Count); System.Diagnostics.Debug.Assert(nodeCounter == coords.Count); // Cad辺単位の処理 // 電気壁節点を記録 for (int barAryIndex = 0; barAryIndex < barArySet.Count; barAryIndex++) { CBarAry barAry = barArySet[barAryIndex]; uint id_barAry = barAry.id; // Note: 頂点のIDの最大値から開始して連番で振られているので、リストインデックスに変換し辛い uint id_e_cad = barAry.id_e_cad; // 電気壁節点、ポート境界節点を記録するための準備 // この辺の属するCadループIDを取得する //uint id_l_cad = getLoopIdOfEdge(EditCad2D, id_e_cad); bool isSharedEdge = CadLogic.isEdgeSharedByLoops(EditCad2D, id_e_cad); // 強制境界か? //この判定は破綻した //// ベースループIDの場合は、境界を除きすべて電気壁 //bool isForcedBoundary = (id_l_cad == BaseLoopId); // この判定も内部の導体対応で破綻した 内部の導体壁(図面的には空洞)が判定できない //辺が2つのループに共有されていないいう条件と導体媒質判定(内部ループ用)を併用して判定する bool isForcedBoundary = false; if (!isSharedEdge) { // 2つのループが共有する辺でない場合ば電気壁(ループに属さない辺がないことが条件) isForcedBoundary = true; } if (!isForcedBoundary) { // 内部の導体判定 // 左右のループIDを取得 uint id_l_l_cad; uint id_l_r_cad; EditCad2D.GetIdLoop_Edge(out id_l_l_cad, out id_l_r_cad, id_e_cad); int mediaIndex_l = CadLogic.VacumnMediaIndex; int mediaIndex_r = CadLogic.VacumnMediaIndex; // 媒質インデックスの取得 CadLogic.Loop workloop; workloop = CadLogic.getLoop(LoopList, id_l_l_cad); mediaIndex_l = workloop.MediaIndex; workloop = CadLogic.getLoop(LoopList, id_l_r_cad); mediaIndex_r = workloop.MediaIndex; if (mediaIndex_l == CadLogic.MetalMediaIndex || mediaIndex_r == CadLogic.MetalMediaIndex) { isForcedBoundary = true; } } // メッシュの辺を走査 for (int barIndex = 0; barIndex < barAry.m_aBar.Count; barIndex++) { SBar bar = barAry.m_aBar[barIndex]; System.Diagnostics.Debug.Assert(bar.v.Length == 2); // 頂点IDを取得(bar.vは頂点のインデックスなので+1する) uint v1 = bar.v[0] + 1; uint v2 = bar.v[1] + 1; string vertexIdsKey = (v2 >= v1) ? string.Format("{0}_{1}", v1, v2) : string.Format("{0}_{1}", v2, v1); if (!edgeToMiddlePtVertexId.ContainsKey(vertexIdsKey)) { // 中点が作成済みでない→導体内のbar // Noye: 1次要素の場合、中点は作成しないが、辺のハッシュとしてedgeToMiddlePtVertexIdを流用している continue; } if (!edgeToBarIndexes.ContainsKey(vertexIdsKey)) { edgeToBarIndexes.Add(vertexIdsKey, new int[] { barAryIndex, barIndex }); } // 境界の辺の節点番号(線要素) int[] nodeNumbers = null; if (order == Constants.FirstOrder) { // 1次線要素 nodeNumbers = new int[] { (int)bar.v[0] + 1, (int)bar.v[1] + 1 }; } else { // 中点 uint vMiddle = 0; if (edgeToMiddlePtVertexId.ContainsKey(vertexIdsKey)) { vMiddle = edgeToMiddlePtVertexId[vertexIdsKey]; } else { // ロジックエラー System.Diagnostics.Debug.Assert(false); } System.Diagnostics.Debug.Assert(vMiddle != 0); // 2次線要素 nodeNumbers = new int[] { (int)bar.v[0] + 1, (int)vMiddle, (int)bar.v[1] + 1 }; } if (isForcedBoundary) { // 電気壁節点の追加 foreach (int nodeNumber in nodeNumbers) { if (!forceBCNodeNumberDic.ContainsKey(nodeNumber)) { forceBCNodeNumberDic.Add(nodeNumber, true); } } } } } // ポート境界上の節点リストを取得する portList.Clear(); foreach (EdgeCollection edgeColleciton in EdgeCollectionList) { IList<int> portNodes = new List<int>(); foreach (uint eId in edgeColleciton.EdgeIds) { CBarAry hitBarAry = null; int hitBarAryIndex = -1; for (int barAryIndex = 0; barAryIndex < barArySet.Count; barAryIndex++) { CBarAry barAry = barArySet[barAryIndex]; uint id_barAry = barAry.id; // Note: 頂点のIDの最大値から開始して連番で振られているので、リストインデックスに変換し辛い uint id_e_cad = barAry.id_e_cad; if (id_e_cad == eId) { hitBarAry = barAry; hitBarAryIndex = barAryIndex; break; } } if (hitBarAry == null) { // ロジックエラー System.Diagnostics.Debug.Assert(false); } // メッシュの辺を走査 IList<int[]> barNodeNumbersList = new List<int[]>(); for (int barIndex = 0; barIndex < hitBarAry.m_aBar.Count; barIndex++) { SBar bar = hitBarAry.m_aBar[barIndex]; System.Diagnostics.Debug.Assert(bar.v.Length == 2); // 頂点IDを取得(bar.vは頂点のインデックスなので+1する) uint v1 = bar.v[0] + 1; uint v2 = bar.v[1] + 1; string vertexIdsKey = (v2 >= v1) ? string.Format("{0}_{1}", v1, v2) : string.Format("{0}_{1}", v2, v1); if (!edgeToBarIndexes.ContainsKey(vertexIdsKey)) { // すでに追加済みのはず System.Diagnostics.Debug.Assert(false); edgeToBarIndexes.Add(vertexIdsKey, new int[] { hitBarAryIndex, barIndex }); } // 境界の辺の節点番号(線要素) int[] nodeNumbers = null; if (order == Constants.FirstOrder) { // 境界の辺の節点番号(1次線要素) nodeNumbers = new int[] { (int)bar.v[0] + 1, (int)bar.v[1] + 1 }; } else { // 中点 uint vMiddle = 0; if (edgeToMiddlePtVertexId.ContainsKey(vertexIdsKey)) { vMiddle = edgeToMiddlePtVertexId[vertexIdsKey]; } else { // ロジックエラー System.Diagnostics.Debug.Assert(false); } System.Diagnostics.Debug.Assert(vMiddle != 0); // 境界の辺の節点番号(2次線要素) nodeNumbers = new int[] { (int)bar.v[0] + 1, (int)vMiddle, (int)bar.v[1] + 1 }; } barNodeNumbersList.Add(nodeNumbers); } // bar if (barNodeNumbersList.Count > 0) { while (barNodeNumbersList.Count > 0) { int[] hitBarNodeNumbers = null; if (portNodes.Count == 0) { hitBarNodeNumbers = barNodeNumbersList[0]; } else { int v_st = portNodes[0]; int v_ed = portNodes[portNodes.Count - 1]; foreach (int[] work in barNodeNumbersList) { int work_v1 = work[0]; int work_v2 = work[work.Length - 1]; if (v_st == work_v1 || v_st == work_v2 || v_ed == work_v1 || v_ed == work_v2) { hitBarNodeNumbers = work; break; } } } if (hitBarNodeNumbers == null) { System.Diagnostics.Debug.Assert(false); break; } barNodeNumbersList.Remove(hitBarNodeNumbers); int v1 = hitBarNodeNumbers[0]; int v2 = hitBarNodeNumbers[hitBarNodeNumbers.Length - 1]; if (portNodes.Count == 0 || v1 == portNodes[portNodes.Count - 1]) { // 最初、or 線要素の始点がリストの終点の場合は、そのまま最後に追加 for (int ino = 0; ino < hitBarNodeNumbers.Length; ino++) { int nodeNumber = hitBarNodeNumbers[ino]; if (portNodes.IndexOf(nodeNumber) >= 0) continue; portNodes.Add(nodeNumber); } } else if (v1 == portNodes[0]) { // 線要素の始点がリストの始点の場合、先頭に逆順で追加 int inscnt = 0; for (int ino = hitBarNodeNumbers.Length - 1; ino >= 0; ino--) { int nodeNumber = hitBarNodeNumbers[ino]; if (portNodes.IndexOf(nodeNumber) >= 0) continue; portNodes.Insert(0 + inscnt, nodeNumber); inscnt++; } } else if (v2 == portNodes[0]) { // 線要素の終点がリストの始点の場合、先頭にそのままの順番で追加 int inscnt = 0; for (int ino = 0; ino < hitBarNodeNumbers.Length; ino++) { int nodeNumber = hitBarNodeNumbers[ino]; if (portNodes.IndexOf(nodeNumber) >= 0) continue; portNodes.Insert(0 + inscnt, nodeNumber); inscnt++; } } else if (v2 == portNodes[portNodes.Count - 1]) { // 線要素の終点がリストの終点の場合、最後に逆順で追加 for (int ino = hitBarNodeNumbers.Length - 1; ino >= 0; ino--) { int nodeNumber = hitBarNodeNumbers[ino]; if (portNodes.IndexOf(nodeNumber) >= 0) continue; portNodes.Add(nodeNumber); } } else { System.Diagnostics.Debug.Assert(false); } //check //System.Diagnostics.Debug.WriteLine("==========="); //foreach (int nodeNumber in portNodes) //{ // System.Diagnostics.Debug.WriteLine(nodeNumber); //} } } } // eId // Mesherの辺はCadの辺の順になっていないので、Cadの辺の順に並び替える if (portNodes.Count > 0) { // 取得したポート節点リストの最後の節点のMesher頂点ID uint work_last_vId_msh = (uint)portNodes[portNodes.Count - 1]; // Cadのポート境界先頭の辺ID uint first_eId_cad = edgeColleciton.EdgeIds[0]; // Cadの辺IDからCadの頂点IDを取得 uint first_id_v1_cad = 0; uint first_id_v2_cad = 0; CadLogic.getVertexIdsOfEdgeId(EditCad2D, first_eId_cad, out first_id_v1_cad, out first_id_v2_cad); // Cadの頂点IDをMesherの頂点IDに変換 uint first_id_v1_msh = Mesher2D.GetElemID_FromCadID(first_id_v1_cad, CAD_ELEM_TYPE.VERTEX); uint first_id_v2_msh = Mesher2D.GetElemID_FromCadID(first_id_v2_cad, CAD_ELEM_TYPE.VERTEX); // 逆順チェック if (work_last_vId_msh == first_id_v1_msh || work_last_vId_msh == first_id_v2_msh) { // 逆順になっているので、辺IDの順に並べ替える int[] saveNodes = portNodes.ToArray(); portNodes.Clear(); for (int i = saveNodes.Length - 1; i >= 0; i--) { portNodes.Add(saveNodes[i]); } } } // ポート節点リストを追加 portList.Add(portNodes); } // edgeCollection //portCounter = portList.Count; // check //foreach (IList<int> portNodes in portList) //{ // System.Diagnostics.Debug.WriteLine("------------"); // foreach (int nodeNumber in portNodes) // { // System.Diagnostics.Debug.WriteLine("{0}: {1}, {2}", nodeNumber, coords[nodeNumber - 1].x, coords[nodeNumber - 1].y); // } //} // 強制境界からポート境界の節点を取り除く // ただし、始点と終点は強制境界なので残す foreach (IList<int> nodes in portList) { for (int i = 0; i < nodes.Count; i++) { if (i != 0 && i != nodes.Count - 1) { int nodeNumber = nodes[i]; if (forceBCNodeNumberDic.ContainsKey(nodeNumber)) { forceBCNodeNumberDic.Remove(nodeNumber); } } } } /////////////////////////////////////////////////////////////// // 節点番号の振り直し // usedVertexIdsリストのインデックス + 1を節点番号にする if (usedVertexIds.Count != coords.Count) { // 座標 // 現在の座標リスト(頂点ID順)を退避 CVector2D[] saveCoordAry = coords.ToArray(); // 座標リストをクリア coords.Clear(); // 空の座標リストを作成 for (int nodeIndex = 0; nodeIndex < usedVertexIds.Count; nodeIndex++) { coords.Add(null); } for (int vIndex = 0; vIndex < saveCoordAry.Length; vIndex++) { uint vId = (uint)vIndex + 1; int nodeIndex_Renumbering = usedVertexIds.IndexOf(vId); if (nodeIndex_Renumbering != -1) { coords[nodeIndex_Renumbering] = saveCoordAry[vIndex]; } } nodeCounter = coords.Count; System.Diagnostics.Debug.Assert(coords.IndexOf(null) == -1); // 要素 foreach (int[] elementData in elements) { // 0: 要素番号 // 1: 媒質インデックス // 2 - 7: 2次三角形要素の節点番号 // 2 - 4: 1次三角形要素の節点番号 for (int i = 2; i < elementData.Length; i++) { uint vId = (uint)elementData[i]; int nodeIndex_Renumbering = usedVertexIds.IndexOf(vId); System.Diagnostics.Debug.Assert(nodeIndex_Renumbering != -1); elementData[i] = nodeIndex_Renumbering + 1; } } // ポート for (int portIndex = 0; portIndex < portList.Count; portIndex++) { IList<int> portNodes = portList[portIndex]; for (int i = 0; i < portNodes.Count; i++) { uint vId = (uint)portNodes[i]; int nodeIndex_Renumbering = usedVertexIds.IndexOf(vId); System.Diagnostics.Debug.Assert(nodeIndex_Renumbering != -1); portNodes[i] = nodeIndex_Renumbering + 1; } } // 強制境界 int[] saveForceBCNodeNumbers = forceBCNodeNumberDic.Keys.ToArray(); forceBCNodeNumberDic.Clear(); foreach (int vId_Int in saveForceBCNodeNumbers) { uint vId = (uint)vId_Int; int nodeIndex_Renumbering = usedVertexIds.IndexOf(vId); System.Diagnostics.Debug.Assert(nodeIndex_Renumbering != -1); int nodeNumber_Renumbering = nodeIndex_Renumbering + 1; if (!forceBCNodeNumberDic.ContainsKey(nodeNumber_Renumbering)) { forceBCNodeNumberDic.Add(nodeNumber_Renumbering, true); } else { System.Diagnostics.Debug.Assert(false); } } } /////////////////////////////////////////////////////////////////////////////////// // Fem入力データファイルのI/Fに合わせる // 座標値 System.Diagnostics.Debug.Assert(doubleCoords.Count == 0); foreach (CVector2D pp in coords) { doubleCoords.Add(new double[] { pp.x, pp.y }); } forceBCNodeNumbers = forceBCNodeNumberDic.Keys.ToArray(); return true; }
/// <summary> /// 問題を設定する /// </summary> /// <returns></returns> private bool setNewProblem() { bool success = false; try { if( ProbNo == 0 ) { CMesher2D mesh2d = null; using(CCadObj2D cad2d = new CCadObj2D()) { IList<CVector2D> pts = new List<CVector2D>(); pts.Add( new CVector2D(0.0,0.0) ); pts.Add( new CVector2D(1.0,0.0) ); pts.Add( new CVector2D(1.0,0.2) ); pts.Add( new CVector2D(0.5,0.2) ); pts.Add( new CVector2D(0.5,0.8) ); pts.Add( new CVector2D(1.0,0.8) ); pts.Add( new CVector2D(1.0,1.0) ); pts.Add( new CVector2D(0.0,1.0) ); cad2d.AddPolygon( pts ); cad2d.ConnectVertex_Line(6,3); mesh2d = new CMesher2D(cad2d,0.05); //// using(CMesher2D msh_tmp = (CMesher2D)mesh2d.Clone()) { mesh2d.Clear(); mesh2d.Dispose(); mesh2d = (CMesher2D)msh_tmp.Clone(); } } using(CSerializer fout = new CSerializer("hoge.txt", false)) { // write file mesh2d.Serialize(fout); } using(CSerializer fin = new CSerializer("hoge.txt", true)) { // load file mesh2d.Serialize(fin); } //// DrawerAry.Clear(); DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) ); DrawerAry.InitTrans( Camera ); mesh2d.Clear(); mesh2d.Dispose(); } else if( ProbNo == 1 ) { string mshfn = "../../../input_file/hexa_tri.msh"; if (File.Exists(mshfn)) { using(CMesher2D mesh2d = new CMesher2D()) { mesh2d.ReadFromFile_GiDMsh(mshfn); using(CSerializer fout = new CSerializer("hoge.txt", false)) { // write file mesh2d.Serialize(fout); } using(CSerializer fin = new CSerializer("hoge.txt", true)) { // load file mesh2d.Serialize(fin); } DrawerAry.Clear(); DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) ); DrawerAry.InitTrans( Camera ); } } else { Console.WriteLine("not exist:{0}", mshfn); MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn)); } } else if( ProbNo == 2 ) { string mshfn = "../../../input_file/rect_quad.msh"; if (File.Exists(mshfn)) { using(CMesher2D mesh2d = new CMesher2D()) { mesh2d.ReadFromFile_GiDMsh(mshfn); using(CSerializer fout = new CSerializer("hoge.txt", false)) { // write file mesh2d.Serialize(fout); } using(CSerializer fin = new CSerializer("hoge.txt", true)) { // load file mesh2d.Serialize(fin); } DrawerAry.Clear(); DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) ); DrawerAry.InitTrans( Camera ); } } else { Console.WriteLine("not exist:{0}", mshfn); MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn)); } } else if( ProbNo == 3 ) { using(CCadObj2D cad2d = new CCadObj2D()) { IList<CVector2D> pts = new List<CVector2D>(); pts.Add( new CVector2D(0.0,0.0) ); pts.Add( new CVector2D(1.0,0.0) ); pts.Add( new CVector2D(1.0,0.5) ); pts.Add( new CVector2D(0.5,0.5) ); pts.Add( new CVector2D(0.5,1.0) ); pts.Add( new CVector2D(0.0,1.0) ); cad2d.AddPolygon( pts ); using(CMesher2D mesh2d = new CMesher2D(cad2d, 0.1)) using(CMesh3D_Extrude mesh3d = new CMesh3D_Extrude()) { mesh3d.Extrude(mesh2d, 0.5, 0.1 ); using(CSerializer fout = new CSerializer("hoge.txt", false)) { // write file mesh3d.Serialize(fout); } using(CSerializer fin = new CSerializer("hoge.txt", true)) { // load file mesh3d.Serialize(fin); } DrawerAry.Clear(); DrawerAry.PushBack( new CDrawerMsh3D(mesh3d) ); DrawerAry.InitTrans( Camera ); } } } else if( ProbNo == 4 ) // load mesh of GiD { string mshfn = "../../../input_file/hexa_tri.msh"; if (File.Exists(mshfn)) { using(CMesher2D mesh2d = new CMesher2D()) using(CMesh3D_Extrude mesh3d = new CMesh3D_Extrude()) { mesh2d.ReadFromFile_GiDMsh(mshfn); mesh3d.Extrude(mesh2d, 5.0, 0.5 ); DrawerAry.Clear(); DrawerAry.PushBack( new CDrawerMsh3D(mesh3d) ); DrawerAry.InitTrans( Camera ); } } else { Console.WriteLine("not exist:{0}", mshfn); MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn)); } } else if( ProbNo == 5 ) { string mshfn = "../../../input_file/cylinder_hex.msh"; if (File.Exists(mshfn)) { using(CMesher3D mesh3d = new CMesher3D()) { mesh3d.ReadFromFile_GiDMsh(mshfn); using(CSerializer fout = new CSerializer("hoge.txt", false)) { // write file mesh3d.Serialize(fout); } using(CSerializer fin = new CSerializer("hoge.txt", true)) { // load file mesh3d.Serialize(fin); } DrawerAry.Clear(); DrawerAry.PushBack( new CDrawerMsh3D(mesh3d) ); DrawerAry.InitTrans( Camera ); } } else { Console.WriteLine("not exist:{0}", mshfn); MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn)); } } else if( ProbNo == 6 ) { string mshfn = "../../../input_file/cylinder_tet.msh"; if (File.Exists(mshfn)) { using(CMesher3D mesh3d = new CMesher3D()) { mesh3d.ReadFromFile_GiDMsh(mshfn); using(CSerializer fout = new CSerializer("hoge.txt", false)) { // write file mesh3d.Serialize(fout); } using(CSerializer fin = new CSerializer("hoge.txt", true)) { // load file mesh3d.Serialize(fin); } DrawerAry.Clear(); DrawerAry.PushBack( new CDrawerMsh3D(mesh3d) ); DrawerAry.InitTrans( Camera ); } } else { Console.WriteLine("not exist:{0}", mshfn); MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn)); } } else if( ProbNo == 7 ) { string mshfn = "../../../input_file/rect_quad.msh"; if (File.Exists(mshfn)) { using(CMesher2D mesh2d = new CMesher2D()) using(CMesh3D_Extrude mesh3d = new CMesh3D_Extrude()) { mesh2d.ReadFromFile_GiDMsh(mshfn); mesh3d.Extrude(mesh2d, 5.0, 0.5 ); DrawerAry.Clear(); DrawerAry.PushBack( new CDrawerMsh3D(mesh3d) ); DrawerAry.InitTrans( Camera ); } } else { Console.WriteLine("not exist:{0}", mshfn); MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn)); } } else if( ProbNo == 8 ) { using(CCadObj2D cad2d = new CCadObj2D()) { uint id_l = 0; { IList<CVector2D> pts = new List<CVector2D>(); pts.Add( new CVector2D(0.0,0.0) ); pts.Add( new CVector2D(1.0,0.0) ); pts.Add( new CVector2D(1.0,1.0) ); pts.Add( new CVector2D(0.0,1.0) ); id_l = cad2d.AddPolygon( pts ).id_l_add; } cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.8,0.6) ); cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.6,0.6) ); cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.4,0.6) ); cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.2,0.6) ); cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.8,0.4) ); cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.6,0.4) ); cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.4,0.4) ); cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.2,0.4) ); using(CMesher2D mesh2d = new CMesher2D(cad2d, 0.02)) { using(CSerializer fout = new CSerializer("hoge.txt", false)) { // write file mesh2d.Serialize(fout); } using(CSerializer fin = new CSerializer("hoge.txt", true)) { // load file mesh2d.Serialize(fin); } DrawerAry.Clear(); DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) ); DrawerAry.InitTrans( Camera ); } } } else if( ProbNo == 9 ) { using(CCadObj2D cad2d = new CCadObj2D()) { { IList<CVector2D> pts = new List<CVector2D>(); pts.Add( new CVector2D(0.0,0.0) ); pts.Add( new CVector2D(1.0,0.0) ); pts.Add( new CVector2D(1.0,1.0) ); pts.Add( new CVector2D(0.0,1.0) ); cad2d.AddPolygon( pts ); } cad2d.SetCurve_Arc(1,true, -0.5); cad2d.SetCurve_Arc(2,false,-0.5); cad2d.SetCurve_Arc(3,true, -0.5); cad2d.SetCurve_Arc(4,false,-0.5); using(CMesher2D mesh2d = new CMesher2D(cad2d, 0.05)) { using(CSerializer fout = new CSerializer("hoge.txt", false)) { // write file mesh2d.Serialize(fout); } using(CSerializer fin = new CSerializer("hoge.txt", true)) { // load file mesh2d.Serialize(fin); } DrawerAry.Clear(); DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) ); DrawerAry.InitTrans( Camera ); } } } else if( ProbNo == 10 ) { using(CCadObj2D cad2d = new CCadObj2D()) { { IList<CVector2D> pts = new List<CVector2D>(); pts.Add( new CVector2D(0.0,0.0) ); pts.Add( new CVector2D(1.0,0.0) ); pts.Add( new CVector2D(1.0,1.0) ); pts.Add( new CVector2D(0.0,1.0) ); uint id_l = cad2d.AddPolygon( pts ).id_l_add; uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.3,0.2)).id_v_add; uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.7,0.2)).id_v_add; uint id_v3 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.7,0.8)).id_v_add; uint id_v4 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.3,0.8)).id_v_add; cad2d.ConnectVertex_Line(id_v1,id_v2); cad2d.ConnectVertex_Line(id_v2,id_v3); cad2d.ConnectVertex_Line(id_v3,id_v4); cad2d.ConnectVertex_Line(id_v4,id_v1); } using(CMesher2D mesh2d = new CMesher2D()) { mesh2d.AddIdLCad_CutMesh(1); // cut mesh to loop whitch have id 1 mesh2d.SetMeshingMode_ElemLength(0.05); mesh2d.Meshing(cad2d); DrawerAry.Clear(); DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) ); DrawerAry.InitTrans( Camera ); } } } else if( ProbNo == 11 ) // mesh with cut { using(CCadObj2D cad2d = new CCadObj2D()) { uint id_l; uint id_e1, id_e2, id_e3, id_e4, id_e5; { IList<CVector2D> pts = new List<CVector2D>(); pts.Add( new CVector2D(0.0,0.0) ); pts.Add( new CVector2D(0.3,0.0) ); pts.Add( new CVector2D(1.0,0.0) ); pts.Add( new CVector2D(1.0,1.0) ); pts.Add( new CVector2D(0.0,1.0) ); id_l = cad2d.AddPolygon( pts ).id_l_add; uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.3,0.5) ).id_v_add; id_e1 = cad2d.ConnectVertex_Line(2,id_v1).id_e_add; uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.7,0.5) ).id_v_add; uint id_v3 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.7,0.2) ).id_v_add; uint id_v4 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.7,0.8) ).id_v_add; uint id_v5 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.5,0.5) ).id_v_add; uint id_v6 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.9,0.5) ).id_v_add; id_e2 = cad2d.ConnectVertex_Line(id_v2,id_v3).id_e_add; id_e3 = cad2d.ConnectVertex_Line(id_v2,id_v4).id_e_add; id_e4 = cad2d.ConnectVertex_Line(id_v2,id_v5).id_e_add; id_e5 = cad2d.ConnectVertex_Line(id_v2,id_v6).id_e_add; } using(CMesher2D mesh2d = new CMesher2D(cad2d, 0.2)) { IList<uint> aIdMsh_Inc = new List<uint>(); aIdMsh_Inc.Add( mesh2d.GetElemID_FromCadID(id_l,CAD_ELEM_TYPE.LOOP) ); IList<uint> aIdMshBar_Cut = new List<uint>(); aIdMshBar_Cut.Add( mesh2d.GetElemID_FromCadID(id_e1,CAD_ELEM_TYPE.EDGE) ); aIdMshBar_Cut.Add( mesh2d.GetElemID_FromCadID(id_e2,CAD_ELEM_TYPE.EDGE) ); aIdMshBar_Cut.Add( mesh2d.GetElemID_FromCadID(id_e3,CAD_ELEM_TYPE.EDGE) ); aIdMshBar_Cut.Add( mesh2d.GetElemID_FromCadID(id_e4,CAD_ELEM_TYPE.EDGE) ); aIdMshBar_Cut.Add( mesh2d.GetElemID_FromCadID(id_e5,CAD_ELEM_TYPE.EDGE) ); //////////////// IList< IList<int> > aLnods = new List<IList<int>>(); IList<uint> mapVal2Co = new List<uint>(); mesh2d.GetClipedMesh(out aLnods, out mapVal2Co, aIdMsh_Inc, aIdMshBar_Cut); DrawerAry.Clear(); DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) ); DrawerAry.InitTrans( Camera ); } } } else if( ProbNo == 12 ) // mesh with cut { using(CCadObj2D cad2d = new CCadObj2D()) { uint id_l1, id_l2; uint id_e3, id_e4; { IList<CVector2D> pts = new List<CVector2D>(); pts.Add( new CVector2D(0.0, 0.0) ); pts.Add( new CVector2D(1.0, 0.0) ); pts.Add( new CVector2D(1.5, 0.0) ); pts.Add( new CVector2D(2.0, 0.0) ); pts.Add( new CVector2D(2.0, 1.0) ); pts.Add( new CVector2D(1.5, 1.0) ); pts.Add( new CVector2D(1.0, 1.0) ); pts.Add( new CVector2D(0.0, 1.0) ); uint id_l0 = cad2d.AddPolygon( pts ).id_l_add; uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l0, new CVector2D(0.5,0.5) ).id_v_add; uint id_e1 = cad2d.ConnectVertex_Line(2,7).id_e_add; uint id_e2 = cad2d.ConnectVertex_Line(3,6).id_e_add; uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE,id_e1, new CVector2D(1.0,0.5) ).id_v_add; uint id_v3 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE,1, new CVector2D(0.5,0.0) ).id_v_add; id_e3 = cad2d.ConnectVertex_Line(id_v1,id_v2).id_e_add; id_e4 = cad2d.ConnectVertex_Line(id_v1,id_v3).id_e_add; id_l1 = 1; id_l2 = 2; } using(CMesher2D mesh2d = new CMesher2D(cad2d, 0.2)) { IList<uint> aIdMsh_Inc = new List<uint>(); aIdMsh_Inc.Add( mesh2d.GetElemID_FromCadID(id_l1,CAD_ELEM_TYPE.LOOP) ); aIdMsh_Inc.Add( mesh2d.GetElemID_FromCadID(id_l2,CAD_ELEM_TYPE.LOOP) ); IList<uint> aIdMshBar_Cut = new List<uint>(); //aIdMshBar_Cut.Add( mesh2d.GetElemID_FromCadID(id_e3,CAD_ELEM_TYPE.EDGE) ); aIdMshBar_Cut.Add( mesh2d.GetElemID_FromCadID(id_e4,CAD_ELEM_TYPE.EDGE) ); //////////////// IList< IList<int> > aLnods = new List<IList<int>>(); IList<uint> mapVal2Co = new List<uint>(); mesh2d.GetClipedMesh(out aLnods, out mapVal2Co, aIdMsh_Inc, aIdMshBar_Cut); DrawerAry.Clear(); DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) ); DrawerAry.InitTrans( Camera ); } } } else if( ProbNo == 13 ) { using(CCadObj2D cad2d = new CCadObj2D()) { { IList<CVector2D> pts = new List<CVector2D>(); pts.Add( new CVector2D(0.0, 0.0) ); // 1 pts.Add( new CVector2D(1.5, 0.0) ); // 2 pts.Add( new CVector2D(1.5, 0.4) ); // 3 pts.Add( new CVector2D(1.0, 0.4) ); // 4 pts.Add( new CVector2D(1.0, 0.5) ); // 5 pts.Add( new CVector2D(2.0, 0.5) ); // 6 pts.Add( new CVector2D(2.0, 1.0) ); // 7 pts.Add( new CVector2D(0.0, 1.0) ); // 8 pts.Add( new CVector2D(0.0, 0.5) ); // 9 uint id_l0 = cad2d.AddPolygon( pts ).id_l_add; uint id_e1 = cad2d.ConnectVertex_Line(5,9).id_e_add; cad2d.ShiftLayer_Loop(id_l0,true); double[] col = new double[3] { 0.9, 0.4, 0.4 }; cad2d.SetColor_Loop(id_l0, col); cad2d.AddVertex(CAD_ELEM_TYPE.EDGE,3, new CVector2D(1.3,0.5)); } using(CMesher2D mesh2d = new CMesher2D(cad2d, 0.05)) { DrawerAry.Clear(); DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) ); DrawerAry.InitTrans( Camera ); } } } else if( ProbNo == 14 ) { string svgfn = "../../../input_file/shape2d_0.svg"; if (File.Exists(svgfn)) { CCadObj2D cad2d = null; CCadSVG.ReadSVG_AddLoopCad(svgfn, out cad2d); using (CMesher2D mesh2d = new CMesher2D()) { mesh2d.SetMeshingMode_ElemSize(400); mesh2d.AddIdLCad_CutMesh(1); mesh2d.Meshing(cad2d); DrawerAry.Clear(); DrawerAry.PushBack(new CDrawerMsh2D(mesh2d)); DrawerAry.InitTrans(Camera); } cad2d.Clear(); cad2d.Dispose(); } else { Console.WriteLine("not exist:{0}", svgfn); MessageBox.Show(string.Format("SVGファイル:{0}がありません", svgfn)); } } success = true; } catch (Exception exception) { Console.WriteLine(exception.Message + " " + exception.StackTrace); } Gl.glMatrixMode(Gl.GL_PROJECTION); Gl.glLoadIdentity(); DrawerGlUtility.SetProjectionTransform(Camera); Glut.glutPostRedisplay(); ProbNo++; if (ProbNo == ProbCnt) ProbNo = 0; return success; }