/// <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;
        }
Beispiel #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="cad2d"></param>
        /// <param name="baseLoopId"></param>
        /// <param name="x0"></param>
        /// <param name="y0"></param>
        /// <param name="rodRadius"></param>
        /// <param name="rodCircleDiv"></param>
        /// <param name="rodRadiusDiv"></param>
        /// <param name="id_v0"></param>
        /// <param name="id_v1"></param>
        /// <param name="id_v2"></param>
        /// <param name="startAngle"></param>
        /// <param name="isReverseAddVertex"></param>
        /// <returns></returns>
        public static uint AddExactlyQuarterRod(CCadObj2D cad2d, uint baseLoopId, double x0, double y0, double rodRadius, int rodCircleDiv, int rodRadiusDiv,
                                                uint id_v0, uint id_v1, uint id_v2, double startAngle, bool isReverseAddVertex)
        {
            CVector2D pt_center = cad2d.GetVertexCoord(id_v1);

            System.Diagnostics.Debug.Assert(Math.Abs(x0 - pt_center.x) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit);
            System.Diagnostics.Debug.Assert(Math.Abs(y0 - pt_center.y) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit);
            List <CVector2D> pts = new List <CVector2D>();

            System.Diagnostics.Debug.Assert((startAngle == 0.0) || (startAngle == 90.0) || (startAngle == 180.0) || (startAngle == 270.0));

            // ロッドの分割数調整
            for (int k = 1; k < rodRadiusDiv; k++)
            {
                for (int itheta = 1; itheta < (rodCircleDiv / 4); itheta++)
                {
                    double theta = 0;
                    if (isReverseAddVertex)
                    {
                        theta = startAngle * pi / 180.0 - itheta * 2.0 * pi / rodCircleDiv;
                    }
                    else
                    {
                        theta = startAngle * pi / 180.0 + itheta * 2.0 * pi / rodCircleDiv;
                    }
                    double x        = x0 + (k * rodRadius / rodRadiusDiv) * Math.Cos(theta);
                    double y        = y0 + (k * rodRadius / rodRadiusDiv) * Math.Sin(theta);
                    uint   id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                }
            }
            uint retLoopId = 0;
            uint prev_id_v = id_v0;

            // ロッド1/4円
            for (int itheta = 1; itheta < (rodCircleDiv / 4); itheta++)
            {
                double theta = 0;
                if (isReverseAddVertex)
                {
                    theta = startAngle * pi / 180.0 - itheta * 2.0 * pi / rodCircleDiv;
                }
                else
                {
                    theta = startAngle * pi / 180.0 + itheta * 2.0 * pi / rodCircleDiv;
                }
                double x        = x0 + rodRadius * Math.Cos(theta);
                double y        = y0 + rodRadius * Math.Sin(theta);
                uint   id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                System.Diagnostics.Debug.Assert(id_v_add != 0);
                CBRepSurface.CResConnectVertex resConnectVertex = cad2d.ConnectVertex_Line(prev_id_v, id_v_add);
                uint id_e_add = resConnectVertex.id_e_add;
                System.Diagnostics.Debug.Assert(id_e_add != 0);
                prev_id_v = id_v_add;
            }
            uint last_id_v = id_v2;

            {
                CBRepSurface.CResConnectVertex resConnectVertex = cad2d.ConnectVertex_Line(prev_id_v, last_id_v);
                uint id_e_add = resConnectVertex.id_e_add;
                uint lId      = resConnectVertex.id_l_add;
                System.Diagnostics.Debug.Assert(id_e_add != 0);
                System.Diagnostics.Debug.Assert(lId != 0);
                retLoopId = lId;
            }

            return(retLoopId);
        }
Beispiel #3
0
        /// <summary>
        /// Glut:マウスクリックイベントハンドラ
        /// </summary>
        /// <param name="button"></param>
        /// <param name="state"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        private void myGlutMouse(int button, int state, int x, int y)
        {
            //Console.WriteLine("myGlutMouse");
            // ryujimiya
            // メニューが左クリックでメニューイベントハンドラが処理された後、MouseUpのイベントが発生する
            // それは望んでいるイベントではないと思われるので除外するようにした。
            if (isMenuItemClicked)
            {
                isMenuItemClicked = false;
                //Console.WriteLine("skipped: state {0}", state);
                return;
            }

            int[] viewport = new int[4];
            Gl.glGetIntegerv(Gl.GL_VIEWPORT, viewport);
            int winW = viewport[2];
            int winH = viewport[3];
            MovBeginX = (2.0 * x - winW) / winW;
            MovBeginY = (winH - 2.0 * y) / winH;
            PressButton = button;

            uint id_part_cad0 = Id_part_cad;
            CAD_ELEM_TYPE elemType_part_cad0 = ElemType_part_cad;
            { // hilight the picked element
                int sizeBuffer = 128;
                DelFEM4NetCom.View.DrawerGlUtility.PickSelectBuffer pickSelectBuffer = null;
                DelFEM4NetCom.View.DrawerGlUtility.PickPre((uint)sizeBuffer, out pickSelectBuffer, (uint)x, (uint)y, 5, 5, Camera);
                DrawerAry.DrawSelection();
                List<DelFEM4NetCom.View.SSelectedObject> aSelecObj = (List<DelFEM4NetCom.View.SSelectedObject>)DelFEM4NetCom.View.DrawerGlUtility.PickPost(pickSelectBuffer, (uint)x, (uint)y, Camera);
                DrawerAry.ClearSelected();

                Id_part_cad = 0;
                elemType_part_cad0 = CAD_ELEM_TYPE.NOT_SET;
                if( aSelecObj.Count > 0 )
                {
                     Drawer.GetCadPartID(aSelecObj[0].name, ref ElemType_part_cad, ref Id_part_cad);
                     DrawerAry.AddSelected( aSelecObj[0].name );
                }
                else
                {
                    ElemType_part_cad = CAD_ELEM_TYPE.NOT_SET;
                    Id_part_cad = 0;
                }
            }
            //Console.WriteLine("ElemType_part_cad: {0}  Id_part_cad: {1}", ElemType_part_cad, Id_part_cad);

            if ( state == Glut.GLUT_DOWN )
            {
                if (Mode == ModeDv.DragCurve)
                {
                    if( ElemType_part_cad == CAD_ELEM_TYPE.EDGE && Cad2D.IsElemID(ElemType_part_cad,Id_part_cad) )
                    {
                        CVector3D oloc = Camera.ProjectionOnPlane(MovBeginX, MovBeginY);
                        if( Cad2D.GetEdgeCurveType(Id_part_cad) == CURVE_TYPE.CURVE_POLYLINE )
                        {
                            bool res = Cad2D.PreCompDragPolyline(Id_part_cad, new CVector2D(oloc.x,oloc.y));
                        }
                        return;
                    }
                }
                else if( Mode == ModeDv.AddPoint )
                {   // add point
                    clearAVec(AVecStrok);
                    if( ElemType_part_cad == CAD_ELEM_TYPE.VERTEX )
                    {
                        return;
                    }
                    CVector3D oloc = Camera.ProjectionOnPlane(MovBeginX, MovBeginY);
                    CVector2D v0 = new CVector2D(oloc.x, oloc.y);
                    uint id_v0 = Cad2D.AddVertex(ElemType_part_cad, Id_part_cad, v0).id_v_add;
                    ElemType_part_cad = CAD_ELEM_TYPE.VERTEX;
                    Id_part_cad = id_v0;
                    if( !Cad2D.IsElemID(CAD_ELEM_TYPE.VERTEX, id_v0) )
                    {
                        clearAVec(AVecStrok);
                        return;
                    }
                    DrawerAry.Clear();
                    if (Drawer != null)
                    {
                        Drawer = null;
                    }
                    Drawer = new CDrawer_Cad2D(Cad2D);
                    DrawerAry.PushBack( Drawer );
                }
                else if( Mode == ModeDv.DeletePoint )
                {   // delete point
                    if( Cad2D.IsElemID(ElemType_part_cad, Id_part_cad) )
                    {
                        bool iflag = Cad2D.RemoveElement(ElemType_part_cad, Id_part_cad);
                        if( iflag )
                        {
                            DrawerAry.Clear();
                            if (Drawer != null)
                            {
                                Drawer = null;
                            }
                            Drawer = new CDrawer_Cad2D(Cad2D);
                            DrawerAry.PushBack( Drawer );
                        }
                    }
                    Mode = ModeDv.Drag;
                    Console.WriteLine("Mode:{0}", Mode);
                }
            }
            if( state == Glut.GLUT_UP )
            {
                if (Mode == ModeDv.AddPoint)
                {
                    //Mode = Mode.Drag;
                    //Console.WriteLine("Mode:{0}", Mode);
                    if (elemType_part_cad0 != CAD_ELEM_TYPE.VERTEX || !Cad2D.IsElemID(CAD_ELEM_TYPE.VERTEX, id_part_cad0))
                    {
                        clearAVec(AVecStrok);
                        return;
                    }
                    uint id_v0 = id_part_cad0;
                    uint id_v1 = 0;
                    if( ElemType_part_cad == CAD_ELEM_TYPE.VERTEX )
                    {
                        if( !Cad2D.IsElemID(CAD_ELEM_TYPE.VERTEX, Id_part_cad) )
                        {
                            clearAVec(AVecStrok);
                            return;
                        }
                        id_v1 = Id_part_cad;
                    }
                    else
                    {
                        CVector2D v1 = AVecStrok[AVecStrok.Count - 1];
                        id_v1 = Cad2D.AddVertex(ElemType_part_cad, Id_part_cad, v1).id_v_add;
                        if( !Cad2D.IsElemID(CAD_ELEM_TYPE.VERTEX,id_v1) )
                        {
                            clearAVec(AVecStrok);
                            return;
                        }
                    }
                    CEdge2D e = new CEdge2D(id_v0,id_v1);
                    {
                        //e.itype = CURVE_TYPE.CURVE_POLYLINE;
                       int n = AVecStrok.Count;
                        CVector2D pos = Cad2D.GetVertexCoord(e.GetIdVtx(true));
                        CVector2D poe = Cad2D.GetVertexCoord(e.GetIdVtx(false));
                        e.SetVtxCoords(pos, poe);
                        double sqlen = CVector2D.SquareLength(poe - pos);
                        CVector2D eh = (poe - pos) * (1/sqlen);
                        CVector2D ev = new CVector2D(-eh.y, eh.x);
                        {
                            IList<double> aRelCo = new List<double>();
                             foreach (CVector2D pp in AVecStrok)
                             {
                                 double x1 = CVector2D.Dot(pp - pos, eh);
                                 double y1 = CVector2D.Dot(pp - pos, ev);
                                 aRelCo.Add(x1);
                                 aRelCo.Add(y1);
                             }
                             e.SetCurve_Polyline(aRelCo);
                        }
                        {
                            IList<CVector2D> aVecDiv = new List<CVector2D>();
                            int ndiv = (int)((double)e.GetCurveLength() / (Camera.GetHalfViewHeight() * 0.04) + 1);
                            e.GetCurveAsPolyline(ref aVecDiv, ndiv);
                            IList<double> aRelCo = new List<double>();
                            foreach (CVector2D pp in aVecDiv)
                            {
                                double x1 = CVector2D.Dot(pp - pos, eh);
                                double y1 = CVector2D.Dot(pp - pos, ev);
                                aRelCo.Add(x1);
                                aRelCo.Add(y1);
                            }
                            e.SetCurve_Polyline(aRelCo);
                        }
                    }
                    Cad2D.ConnectVertex(e);
                    DrawerAry.Clear();
                    if (Drawer != null)
                    {
                        Drawer = null;
                    }
                    Drawer = new CDrawer_Cad2D(Cad2D);
                    DrawerAry.PushBack( Drawer );
                    clearAVec(AVecStrok);
                }
            }
        }
        /// <summary>
        /// Ver1.2.0.0形式の図面ファイルから読み込み(Ver1.2.0.0→Ver1.3.0.0の変換あり)
        /// </summary>
        /// <param name="in_filename"></param>
        /// <param name="isBackupFile">バックアップファイル?</param>
        /// <param name="out_cad2d">格納先Cadオブジェクトのリファレンス</param>
        /// <param name="out_LoopList">ループ情報のリスト</param>
        /// <param name="out_edgeCollectionList">ポートのエッジコレクションのリスト</param>
        /// <param name="out_incidentPortNo">入射ポート番号</param>
        /// <param name="out_medias">媒質情報リストのリファレンス(比誘電率、比透磁率だけセットされる)</param>
        /// <returns></returns>
        public static bool LoadFromFile_Ver_1_2(
            string in_filename,
            out bool isBackupFile,
            ref CCadObj2D out_cad2d,
            ref IList<CadLogic.Loop> out_LoopList,
            ref IList<EdgeCollection> out_edgeCollectionList,
            out int out_incidentPortNo,
            ref MediaInfo[] out_medias
            )
        {
            bool success = false;

            ////////////////////////////////////////////////////////
            // 出力データの初期化

            // バックアップファイル?
            isBackupFile = false;
            // 図面のクリア
            out_cad2d.Clear();
            // ループ情報リストの初期化
            out_LoopList.Clear();
            // 入射ポートの初期化
            out_incidentPortNo = 1;
            // ポートのエッジコレクションのリストを初期化
            out_edgeCollectionList.Clear();
            // 媒質の比誘電率、比透磁率の逆数の初期化
            foreach (MediaInfo media in out_medias)
            {
                // 比透磁率の逆数
                media.SetP(new double[,]
                    {
                        {1.0, 0.0, 0.0},
                        {0.0, 1.0, 0.0},
                        {0.0, 0.0, 1.0}
                    });
                // 比誘電率
                media.SetQ(new double[,]
                    {
                        {1.0, 0.0, 0.0},
                        {0.0, 1.0, 0.0},
                        {0.0, 0.0, 1.0}
                    });
            }

            ////////////////////////////////////////////////////////
            // バックアップファイルの作成
            string filename = "";
            if (in_filename.IndexOf(Ver1_2_Backup_Suffix) >= 0)
            {
                isBackupFile = true;
                MessageBox.Show("このファイルはバックアップファイルです。このファイルを上書き保存しないようご注意ください。",
                    "旧データ形式からの変換", MessageBoxButtons.OK, MessageBoxIcon.Information);

                // 入力ファイル名をそのまま利用
                filename = in_filename;
            }
            else
            {
                // 指定されたCadファイルとその入出力データをリネームする
                string basename = Path.GetDirectoryName(in_filename) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(in_filename);
                string inputfilename = basename + Constants.FemInputExt;
                string outputfilename = basename + Constants.FemOutputExt;
                string indexfilename = outputfilename + Constants.FemOutputIndexExt;
                //ReadOnlyにするのを止める
                ////FEM入出力データは移動しない(Ver1.2のアプリで再計算すると落ちるので止めます:データ削除でtry catchしていないのが原因だと思われる)
                //string[] tagtfilenames = { in_filename };
                // 全ファイルを移動する
                string[] tagtfilenames = { in_filename, inputfilename, outputfilename, indexfilename };
                foreach (string tagtfilename in tagtfilenames)
                {
                    string fname = Path.GetFileNameWithoutExtension(tagtfilename);
                    string ext = Path.GetExtension(tagtfilename);
                    if (fname != Path.GetFileNameWithoutExtension(fname)) // .out.idxの場合、ファイル名に.outまで入るので小細工する
                    {
                        string ext2 = Path.GetExtension(fname);
                        string fname2 = Path.GetFileNameWithoutExtension(fname);
                        ext = ext2 + ext;
                        fname = fname2;
                    }
                    string tagtbasename = Path.GetDirectoryName(tagtfilename) + Path.DirectorySeparatorChar + fname;
                    string backupFilename = tagtbasename + Ver1_2_Backup_Suffix + ext;
                    if (File.Exists(tagtfilename))
                    {
                        if (!File.Exists(backupFilename))
                        {
                            // 対象ファイルが存在し、かつバックアップファイルが存在しないとき
                            //バックアップファイルの作成
                            //MyUtilLib.MyUtil.MoveFileWithReadOnly(tagtfilename, backupFilename);
                            try
                            {
                                // そのまま移動(更新時刻等の再設定が面倒なのでコピーでなく移動する)
                                File.Move(tagtfilename, backupFilename);

                                // コピーとして戻す
                                File.Copy(backupFilename, tagtfilename);
                            }
                            catch (Exception exception)
                            {
                                System.Diagnostics.Debug.WriteLine(exception.Message + " " + exception.StackTrace);
                                MessageBox.Show(exception.Message);
                            }
                        }
                        else
                        {
                            // 対象ファイルは存在し、バックアップが存在するとき
                            // バックアップを作成できない
                            MessageBox.Show("すでに別のバックアップファイルがあるので、バックアップを作成できません。このファイルを上書き保存しないようご注意ください。",
                                "旧データ形式からの変換", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                    }
                }

                // バックアップファイルに移動したので、バックアップファイルから読み込む
                filename = basename + Ver1_2_Backup_Suffix + Constants.CadExt;
            }

            // Ver1.2.0.0形式のファイルの読み込み
            Size maxDiv;
            bool[,] areaSelection;
            int[,] areaToMediaIndex;
            IList<CadDatFile_Ver_1_2.Edge_Ver_1_2> edgeList_Ver_1_2;
            bool[,] yBoundarySelection;
            bool[,] xBoundarySelection;
            int incidentPortNo_Ver_1_2;
            MediaInfo[] medias_Ver_1_2;

            bool loadSuccess = false;
            loadSuccess = CadDatFile_Ver_1_2.LoadFromFile_Ver_1_2(
                filename, out maxDiv, out areaSelection, out areaToMediaIndex,
                out edgeList_Ver_1_2, out yBoundarySelection, out xBoundarySelection,
                out incidentPortNo_Ver_1_2, out medias_Ver_1_2
                );
            if (!loadSuccess)
            {
                return success;
            }

            /////////////////////////////////////////////////////////////////////////////////
            // 本バージョンへのデータ変換
            /////////////////////////////////////////////////////////////////////////////////

            /////////////////////////////////////////////////////////////////////////////////
            // そのまま使用できる情報
            out_incidentPortNo = incidentPortNo_Ver_1_2;

            /////////////////////////////////////////////////////////////////////////////////
            // 変換が必要な情報
            // Medias --> インデックスを1加算
            // AreaToMediaIndex --> インデックスを1加算
            // AreaSelection, AreaToMediaIndex  --> loop
            // EdgeVer1_2 --> EdgeCollection

            //////////////////////////
            // 媒質情報は、Ver1.2→Ver1.3で媒質インデックスが1つずれる(導体が追加されたため)
            for (int oldMediaIndex = 0; oldMediaIndex < medias_Ver_1_2.Length; oldMediaIndex++)
            {
                if (oldMediaIndex + 1 < out_medias.Length)
                {
                    int mediaIndex = oldMediaIndex + 1;  //インデックスを1加算
                    out_medias[mediaIndex].SetP(medias_Ver_1_2[oldMediaIndex].P);
                    out_medias[mediaIndex].SetQ(medias_Ver_1_2[oldMediaIndex].Q);
                }
            }
            for (int y = 0; y < maxDiv.Height; y++)
            {
                for (int x = 0; x < maxDiv.Width; x++)
                {
                    areaToMediaIndex[y, x]++; //インデックスを1加算
                }
            }

            ///////////////////////////
            // 変換準備
            /*
            // 領域選択情報を媒質情報にマージする(非選択の場合もインデックスは0が設定されているがこれを-1に変更)
            for (int y = 0; y < maxDiv.Height; y++)
            {
                for (int x = 0; x < maxDiv.Width; x++)
                {
                    if (!areaSelection[y, x])
                    {
                        // エリアが選択されていない
                        areaToMediaIndex[y, x] = -1; // 未指定に設定する
                    }
                }
            }
             */
            // 非選択部分は導体媒質を設定する
            for (int y = 0; y < maxDiv.Height; y++)
            {
                for (int x = 0; x < maxDiv.Width; x++)
                {
                    if (!areaSelection[y, x])
                    {
                        // エリアが選択されていない
                        areaToMediaIndex[y, x] = CadLogic.MetalMediaIndex; // 導体を指定する
                    }
                }
            }

            // ループの取得
            IList<DelFEM4NetCom.Pair<int, IList<Point>>> loopList = getLoopList(maxDiv, areaToMediaIndex);

            // ループをエッジに変換
            IList<IList<CadDatFile_Ver_1_2.Edge_Ver_1_2>> loopEdgeListList = getLoopEdgeList(loopList);

            // ポート境界のエッジリスト分、エッジコレクションを先に作成する(複数のループにまたがる場合があるため)
            foreach (CadDatFile_Ver_1_2.Edge_Ver_1_2 portEdge in edgeList_Ver_1_2)
            {
                EdgeCollection edgeCollection = new EdgeCollection();
                edgeCollection.No = portEdge.No;
                out_edgeCollectionList.Add(edgeCollection);
            }

            var newLoopEdgeListList = new List<IList<CadDatFile_Ver_1_2.Edge_Ver_1_2>>();
            // ループ数分チェック
            foreach (IList<CadDatFile_Ver_1_2.Edge_Ver_1_2> loopEdgeList in loopEdgeListList)
            {
                // 1つのループ
                var newLoopEdgeList = new List<CadDatFile_Ver_1_2.Edge_Ver_1_2>();
                foreach (CadDatFile_Ver_1_2.Edge_Ver_1_2 loopEdge in loopEdgeList)
                {
                    // 1つのエッジ

                    // ポート境界を含んでいれば分解する
                    // 頂点リスト
                    IList<Point> vertexPts = new List<Point>();
                    // 頂点にポートが対応していれば、ポート番号を格納
                    // 既定値は -1
                    IList<int> toPortNo = new List<int>();

                    // エッジの最初の頂点を追加
                    vertexPts.Add(loopEdge.Points[0]);
                    toPortNo.Add(-1);

                    // ポート境界のエッジリストを走査
                    foreach (CadDatFile_Ver_1_2.Edge_Ver_1_2 portEdge in edgeList_Ver_1_2)
                    {
                        // contains?
                        Point minPt;
                        Point maxPt;
                        if (loopEdge.Contains(portEdge, out minPt, out maxPt))
                        {
                            // ポート境界が含まれていた
                            // ポート境界の頂点を追加
                            //vertexPts.Add(portEdge.Points[0]); // 始点
                            //vertexPts.Add(portEdge.Points[1]); // 終点
                            vertexPts.Add(minPt); // 始点
                            vertexPts.Add(maxPt); // 終点
                            // ポート番号を頂点にあわせて追加
                            toPortNo.Add(portEdge.No);
                            toPortNo.Add(portEdge.No);
                        }
                        else if (loopEdge.GetSimpleSwap().Contains(portEdge, out minPt, out maxPt))
                        {
                            // ポート境界の頂点を追加
                            //vertexPts.Add(portEdge.Points[1]);  // swap 終点
                            //vertexPts.Add(portEdge.Points[0]);  // swap 始点
                            vertexPts.Add(maxPt);  // swap 終点
                            vertexPts.Add(minPt);  // swap 始点
                            // ポート番号を頂点にあわせて追加
                            toPortNo.Add(portEdge.No);
                            toPortNo.Add(portEdge.No);
                        }
                    }
                    // 最後の頂点を追加
                    vertexPts.Add(loopEdge.Points[1]);
                    toPortNo.Add(-1);

                    // 頂点を元にしてエッジを再構築
                    for (int ino = 0; ino < vertexPts.Count - 1; ino++)
                    {
                        CadDatFile_Ver_1_2.Edge_Ver_1_2 work = new CadDatFile_Ver_1_2.Edge_Ver_1_2();
                        // ポート番号があれば格納
                        if (toPortNo[ino] != -1)
                        {
                            work.No = toPortNo[ino];
                        }
                        else
                        {
                            work.No = 0;
                        }
                        // 辺の始点、終点
                        work.Points[0] = vertexPts[ino];
                        work.Points[1] = vertexPts[ino + 1];
                        // Deltaの計算&格納
                        Point p1 = work.Points[0];
                        Point p2 = work.Points[1];
                        work.Delta = CadDatFile_Ver_1_2.Edge_Ver_1_2.CalcDelta(p1, p2);

                        // 空チェック
                        if (work.IsEmpty())
                        {
                            // 空の場合追加しない
                        }
                        else
                        {
                            // 追加
                            newLoopEdgeList.Add(work);
                        }
                    }
                    // 1つのエッジ再構築終了

                } // エッジ

                // 1つのループのエッジリストをリストに追加
                newLoopEdgeListList.Add(newLoopEdgeList);
            } // ループ

            ///////////////////////////////////////////////////////////////////
            // version1.3.0.0のデータ構造に反映する
            bool errorCCadObj = false;

            // ループ領域を作成
            //uint baseLoopId = 0;
            for (int loopIndex = 0; loopIndex < loopList.Count; loopIndex++)
            {
                System.Diagnostics.Debug.WriteLine("loopIndex: {0}", loopIndex);
                DelFEM4NetCom.Pair<int, IList<Point>> loop = loopList[loopIndex];
                // 媒質インデックス
                int mediaIndex = loop.First;
                // ループを構成する頂点
                IList<Point> pts = loop.Second;

                IList<CVector2D> pps = new List<CVector2D>();
                /*
                foreach (Point pt in pts)
                {
                    double xx = pt.X - maxDiv.Width * 0.5;
                    double yy = maxDiv.Height - pt.Y - maxDiv.Height * 0.5;
                    pps.Add(new CVector2D(xx, yy));
                }
                 */
                // このループのエッジリストを取得する
                IList<CadDatFile_Ver_1_2.Edge_Ver_1_2> loopEdgeList = newLoopEdgeListList[loopIndex];

                // エッジのリストインデックス→エッジコレクションのリストのインデックス変換マップ
                IList<int> loopEdgeIndexToEdgeCollectionIndex = new List<int>();

                // OpenGlの頂点リストを作成
                for (int loopEdgeIndex = 0; loopEdgeIndex < loopEdgeList.Count; loopEdgeIndex++)
                {
                    // エッジ
                    CadDatFile_Ver_1_2.Edge_Ver_1_2 work = loopEdgeList[loopEdgeIndex];

                    ////////////////////////////////
                    // OpenGlの頂点作成
                    double xx;
                    double yy;
                    Point pt;
                    pt = work.Points[0]; //始点を追加していく
                    xx = pt.X - maxDiv.Width * 0.5;
                    yy = maxDiv.Height - pt.Y - maxDiv.Height * 0.5;
                    pps.Add(new CVector2D(xx, yy));
                    System.Diagnostics.Debug.WriteLine("pps[{0}]: {1}, {2}", pps.Count - 1, pps[pps.Count - 1].x, pps[pps.Count - 1].y);

                    // check: 終点は次のエッジの始点のはず
                    if (loopEdgeIndex < loopEdgeList.Count - 1)
                    {
                        CadDatFile_Ver_1_2.Edge_Ver_1_2 next = loopEdgeList[loopEdgeIndex + 1];
                        System.Diagnostics.Debug.Assert(work.Points[1].Equals(next.Points[0]));
                    }

                    /* ループの最後の点は追加しない
                    if (loopEdgeIndex == loopEdgeList.Count - 1)
                    {
                        // 最後だけ終点を追加
                        pt = work.Points[1];
                        xx = pt.X - maxDiv.Width * 0.5;
                        yy = maxDiv.Height - pt.Y - maxDiv.Height * 0.5;
                        pps.Add(new CVector2D(xx, yy));
                    }
                    */

                    int edgeCollectionIndex = -1;
                    if (work.No != 0)
                    {
                        ////////////////////////////////////////////////////////
                        // ポート情報がある場合
                        // check
                        {
                            EdgeCollection edgeCollection = out_edgeCollectionList[work.No - 1];
                            System.Diagnostics.Debug.Assert(work.No == edgeCollection.No);
                        }
                        // エッジコレクションリストのインデックスをセット
                        edgeCollectionIndex = work.No - 1;
                    }
                    // エッジのリストインデックス→エッジコレクションのリストのインデックス変換マップ(ポートがない場合も-1で追加する)
                    loopEdgeIndexToEdgeCollectionIndex.Add(edgeCollectionIndex);
                } // loopEdgeIndex

                uint id_l = 0;
                // 多角形でループを作成するのを止める
                //uint id_l = out_cad2d.AddPolygon(pps, baseLoopId).id_l_add;
                // 自力でループ作成
                System.Diagnostics.Debug.WriteLine("makeLoop: loopIndex: {0}", loopIndex);
                id_l = CadLogic.makeLoop(out_cad2d, pps, out_LoopList, false);
                if (id_l == 0)
                {
                    // 領域分割でできた領域は、現状取り込みを実装していません。
                    MessageBox.Show("領域の追加に失敗しました。");
                    errorCCadObj = true;
                }
                else
                {
                    //////////////////////////////////////////////////////////////////////
                    // 辺と頂点を取得
                    IList<uint> vIdList = null;
                    IList<uint> eIdList = null;
                    CadLogic.GetEdgeVertexListOfLoop(out_cad2d, id_l, out vIdList, out eIdList);
                    // 元々の辺のインデックスに対して生成された辺のIDのリストを要素とするリスト
                    IList<IList<uint>> generatedEIdsList = new List<IList<uint>>();
                    // ループ作成時に辺が分割された場合も考慮
                    int eIdIndexOfs = 0;
                    System.Diagnostics.Debug.WriteLine("pps[0]: {0},{1}", pps[0].x, pps[0].y);
                    {
                        Edge_Ver_1_2 loopEdge0 = loopEdgeList[0];
                        CVector2D loopEdge0_pp_v1;
                        CVector2D loopEdge0_pp_v2;
                        {
                            double xx;
                            double yy;
                            Point pt;
                            pt = loopEdge0.Points[0];
                            xx = pt.X - maxDiv.Width * 0.5;
                            yy = maxDiv.Height - pt.Y - maxDiv.Height * 0.5;
                            loopEdge0_pp_v1 = new CVector2D(xx, yy);
                            pt = loopEdge0.Points[1];
                            xx = pt.X - maxDiv.Width * 0.5;
                            yy = maxDiv.Height - pt.Y - maxDiv.Height * 0.5;
                            loopEdge0_pp_v2 = new CVector2D(xx, yy);
                        }
                        System.Diagnostics.Debug.WriteLine("loopEdge0_pp_v1: {0},{1} loopEdge0_pp_v2: {2},{3}", loopEdge0_pp_v1.x, loopEdge0_pp_v1.y, loopEdge0_pp_v2.x, loopEdge0_pp_v2.y);
                        for (int eIdIndexSearch = 0; eIdIndexSearch < eIdList.Count; eIdIndexSearch++)
                        {
                            uint id_e = eIdList[eIdIndexSearch];
                            bool isIncluding = CadLogic.isEdgeIncludingEdge(out_cad2d, loopEdge0_pp_v1, loopEdge0_pp_v2, id_e);
                            if (isIncluding)
                            {
                                eIdIndexOfs = eIdIndexSearch;
                                break;
                            }
                        }
                    }
                    System.Diagnostics.Debug.WriteLine("eIdIndexOfs:{0}", eIdIndexOfs);

                    for (int loopEdgeIndex = 0; loopEdgeIndex < loopEdgeList.Count; loopEdgeIndex++)
                    {
                        IList<uint> generatedEIds = new List<uint>();
                        Edge_Ver_1_2 loopEdge = loopEdgeList[loopEdgeIndex];
                        CVector2D loopEdge_pp_v1;
                        CVector2D loopEdge_pp_v2;
                        {
                            double xx;
                            double yy;
                            Point pt;
                            pt = loopEdge.Points[0];
                            xx = pt.X - maxDiv.Width * 0.5;
                            yy = maxDiv.Height - pt.Y - maxDiv.Height * 0.5;
                            loopEdge_pp_v1 = new CVector2D(xx, yy);
                            pt = loopEdge.Points[1];
                            xx = pt.X - maxDiv.Width * 0.5;
                            yy = maxDiv.Height - pt.Y - maxDiv.Height * 0.5;
                            loopEdge_pp_v2 = new CVector2D(xx, yy);
                        }
                        System.Diagnostics.Debug.WriteLine("  loopEdgeIndex:{0}", loopEdgeIndex);
                        System.Diagnostics.Debug.WriteLine("    loopEdge_pp_v1: {0},{1} loopEdge0_pp_v2: {2},{3}", loopEdge_pp_v1.x, loopEdge_pp_v1.y, loopEdge_pp_v2.x, loopEdge_pp_v2.y);
                        for (int eIdIndex = 0; eIdIndex < eIdList.Count; eIdIndex++)
                        {
                            uint id_e = eIdList[(eIdIndex + eIdIndexOfs) % eIdList.Count]; // 1つずらして取得
                            //System.Diagnostics.Debug.WriteLine("            {0} id_e:{1}", (eIdIndex + eIdIndexOfs) % eIdList.Count, id_e);
                            bool isIncluding = CadLogic.isEdgeIncludingEdge(out_cad2d, loopEdge_pp_v1, loopEdge_pp_v2, id_e);
                            if (!isIncluding)
                            {
                                continue;
                            }
                            generatedEIds.Add(id_e);
                            // check
                            {
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                CadLogic.getVertexIdsOfEdgeId(out_cad2d, id_e, out id_v1, out id_v2);
                                CVector2D pp_v1 = out_cad2d.GetVertexCoord(id_v1);
                                CVector2D pp_v2 = out_cad2d.GetVertexCoord(id_v2);
                                System.Diagnostics.Debug.WriteLine("    eId: {0}, pp_v1: {1},{2} pp_v2: {3},{4}", id_e, pp_v1.x, pp_v1.y, pp_v2.x, pp_v2.y);
                            }
                        }
                        generatedEIdsList.Add(generatedEIds);
                    }

                    ///////////////////////////////////////////////////////////////////////
                    // エッジコレクションにポート境界に対応する辺のIDをセットする
                    //IList<EdgeCollection> workEdgeCollectionList = new List<EdgeCollection>();  // ここで辺のIDをセットしたコレクションを辺の色付けのために一時保管する
                    for (int loopEdgeIndex = 0; loopEdgeIndex < loopEdgeList.Count; loopEdgeIndex++)
                    {
                        int edgeCollectionIndex = loopEdgeIndexToEdgeCollectionIndex[loopEdgeIndex];
                        if (edgeCollectionIndex != -1)
                        {
                            //
                            EdgeCollection edgeCollection = out_edgeCollectionList[edgeCollectionIndex];
                            IList<uint> generatedEIds = generatedEIdsList[loopEdgeIndex];
                            foreach (uint id_e in generatedEIds)
                            {
                                // 辺のIDをエッジコレクションにセット
                                // 辺の連続性はここではチェックしない(ばらばらで追加されるので)
                                bool chkFlg = false;
                                if (!edgeCollection.ContainsEdgeId(id_e))
                                {
                                    bool ret = edgeCollection.AddEdgeId(id_e, out_cad2d, chkFlg);
                                }
                            }

                            // 一時保管
                            //workEdgeCollectionList.Add(edgeCollection);
                        }
                    }
                    ////////////////////////////////////////////////////////////////////////
                    // 最初のループならばそのIdを記録する
                    //if (baseLoopId == 0)
                    //{
                    //    baseLoopId = id_l;
                    //}
                    // ループの情報を追加する
                    out_LoopList.Add(new CadLogic.Loop(id_l, mediaIndex));

                    // まだ処理が完全でないので下記は処理しない
                    // ループの内側にあるループを子ループに設定する
                    //CadLogic.reconstructLoopsInsideLoopAsChild(out_cad2d, id_l, ref out_LoopList, ref out_edgeCollectionList, out_medias, ref out_incidentPortNo);

                    ////////////////////////////////////////////////////////////////////////
                    // Cadオブジェクトの色をセットする
                    // ループとその辺、頂点の色をセット
                    MediaInfo media = out_medias[mediaIndex];
                    Color backColor = media.BackColor;
                    CadLogic.SetupColorOfCadObjectsForOneLoop(out_cad2d, id_l, backColor);
                    // ポートの色をセットする
                    //CadLogic.SetupColorOfPortEdgeCollection(out_cad2d, workEdgeCollectionList, incidentPortNo_Ver_1_2);
                } // if id_l != 0
            } // loopIndex

            // 番号順に並び替え
            ((List<EdgeCollection>)out_edgeCollectionList).Sort();
            // エッジコレクションの辺IDリストをソートする
            foreach (EdgeCollection workEdgeCollection in out_edgeCollectionList)
            {
                bool ret = workEdgeCollection.SortEdgeIds(out_cad2d);
            }

            // ポートの色をセットする
            CadLogic.SetupColorOfPortEdgeCollection(out_cad2d, out_edgeCollectionList, out_incidentPortNo);

            /////////////////////////////////////////////
            // 外側の導体媒質ループ削除処理
            //
            // 外側の導体媒質ループを取得する
            IList<CadLogic.Loop> delLoopList = new List<CadLogic.Loop>();
            foreach (CadLogic.Loop loop in out_LoopList)
            {
                if (loop.MediaIndex == CadLogic.MetalMediaIndex) // 導体の場合のみ実行
                {
                    // 外側の判定 --->他のループと共有していない辺が存在する
                    IList<uint> vIdList = null;
                    IList<uint> eIdList = null;
                    CadLogic.GetEdgeVertexListOfLoop(out_cad2d, loop.LoopId, out vIdList, out eIdList);

                    bool notSharedEdgeExists = false;
                    foreach (uint eId in eIdList)
                    {
                        if (CadLogic.isEdgeSharedByLoops(out_cad2d, eId))
                        {
                            // 辺を2つのループで共有している
                        }
                        else
                        {
                            // 辺を共有していない
                            notSharedEdgeExists = true;
                            break;
                        }
                    }
                    if (notSharedEdgeExists)
                    {
                        delLoopList.Add(loop);
                    }
                }
            }
            // 外側の導体媒質ループを削除
            foreach (CadLogic.Loop deltarget in delLoopList)
            {
                CadLogic.delLoop(out_cad2d, deltarget.LoopId, ref out_LoopList, ref out_edgeCollectionList, out_medias, ref out_incidentPortNo);
            }

            if (errorCCadObj)
            {
                success = false;
            }
            else
            {
                success = true;
            }
            return success;
        }