//yが最小の点を探す。複数あるならxが低い方 public static int findMinYPointIndex(LDPointList points) { if (points.length() == 0) { return(-1); } int length = points.length(); double minY = points[0].y(); for (int i = 0; i < length; ++i) { if (points[i].y() < minY) { minY = points[i].y(); } } List <int> minYList = new List <int>(); for (int i = 0; i < length; ++i) { if (points[i].y() == minY) { minYList.Add(i); } } Debug.Assert(minYList.Count != 0); if (minYList.Count == 1) { return(minYList[0]); } float minX = points[minYList[0]].x(); int minXIndex = minYList[0]; for (int i = 0; i < minYList.Count; ++i) { int index = minYList[i]; if (points[index].x() < minX) { minXIndex = index; } } return(minXIndex); }
//yが最小の点を探す。複数あるならxが低い方 public static int findMinYPointIndex(LDPointList points) { if (points.length() == 0) { return -1; } int length = points.length(); double minY = points[0].y(); for (int i = 0; i < length; ++i) { if (points[i].y() < minY) { minY = points[i].y(); } } List<int> minYList = new List<int>(); for (int i = 0; i < length; ++i) { if (points[i].y() == minY) { minYList.Add(i); } } Debug.Assert(minYList.Count != 0); if (minYList.Count == 1) { return minYList[0]; } float minX = points[minYList[0]].x(); int minXIndex = minYList[0]; for (int i = 0; i < minYList.Count; ++i) { int index = minYList[i]; if (points[index].x() < minX) { minXIndex = index; } } return minXIndex; }
//特定の三角形から始めて、周辺の四角形をフリップすることで分割形状を最適化する。 private static void optimizePolygonSeparate(LDPointList form, LDTriangle firstTriangle, LDTriangleList triangles) { LDIndexLineList uncheckedLines = new LDIndexLineList(); uncheckedLines.Add(firstTriangle.getLine1()); uncheckedLines.Add(firstTriangle.getLine2()); uncheckedLines.Add(firstTriangle.getLine3()); //A2-2) スタックSが空になるまで以下を繰り返す while (uncheckedLines.size() != 0) { //A2-2-1) スタックSの一番上のedgeをpopする.これを辺ABとする LDIndexLine lineAB = uncheckedLines.Last(); uncheckedLines.RemoveAt(uncheckedLines.Count - 1); //線と接する2つの三角形を取得 LDTriangleList relatedTriangles = triangles.find(lineAB); //外周はチェックしない if (relatedTriangles.size() == 1) { continue; } //三角形がダブってるのは不正。隣接0もなにかおかしい Debug.Assert(relatedTriangles.size() == 2); //A2-2-2) 辺ABを含む2個の三角形をABCとABDとする // if(三角形ABCの外接円内にDが入 る) 辺ABをflipし,辺AD/DB/BC/CAをスタックSにpushする //else 何もしない LDTriangle triangleABC = relatedTriangles.at(0); LDTriangle triangleABD = relatedTriangles.at(1); int index = triangleABD.getIndexWithoutLine(lineAB); Debug.Assert(form.length() > index); LDPoint pd = form[index]; // 外接円を求める LDCircle c = LDCircle.getCircumscribedCirclesOfTriangle(form, triangleABC); double dist = PointUtil.distance(c.center, pd); //誤差の範囲ならフリップしない if (dist < c.radius && Math.Abs(c.radius - dist) > 0.00001) { //不正な辺 uncheckedLines.AddRange(flipTriangles(triangleABC, triangleABD, lineAB, triangles)); } } }
public static LDTriangleList exec(LDPointList form)//TODO ,LDProgress progress { //Debug.Assert(form.length() == form.toList().toSet().size()); LDTriangleList result = new LDTriangleList(); int formSize = form.size(); if (formSize < 2) { return(result); } //A1) 点群を包含する十分大きな三角形(super triangle)を追加する LDPolygon hugeTriangle = TriangleUtil.getHugeTriangle(form); int index1 = form.length(); int index2 = index1 + 1; int index3 = index2 + 1; form.Add(hugeTriangle[0]); form.Add(hugeTriangle[1]); form.Add(hugeTriangle[2]); LDTriangle t = new LDTriangle(index1, index2, index3); result.Add(t); //A2) i番目の頂点piを三角形分割図形に追加 for (int i = 0; i < formSize; i++) { LDPoint pi = form[i]; // A2-1) piを含む三角形ABCを発見し, この三角形をAB pi, BC pi, CA pi の3個の三角形に分割. triangulationFromPoint(form, pi, result); } // 最後に、外部三角形の頂点を削除 result.removePoint(index1); result.removePoint(index2); result.removePoint(index3); return(result); } // static LDTriangleList exec(LDPointList form,LDIndexLineList limitedLines);//TODO ,LDProgress progress
//TODO ,LDProgress progress public static LDTriangleList exec(LDPointList form) { //Debug.Assert(form.length() == form.toList().toSet().size()); LDTriangleList result = new LDTriangleList(); int formSize = form.size(); if (formSize < 2) { return result; } //A1) 点群を包含する十分大きな三角形(super triangle)を追加する LDPolygon hugeTriangle = TriangleUtil.getHugeTriangle(form); int index1 = form.length(); int index2 = index1 + 1; int index3 = index2 + 1; form.Add(hugeTriangle[0]); form.Add(hugeTriangle[1]); form.Add(hugeTriangle[2]); LDTriangle t = new LDTriangle(index1, index2, index3); result.Add(t); //A2) i番目の頂点piを三角形分割図形に追加 for (int i = 0; i < formSize; i++) { LDPoint pi = form[i]; // A2-1) piを含む三角形ABCを発見し, この三角形をAB pi, BC pi, CA pi の3個の三角形に分割. triangulationFromPoint(form, pi, result); } // 最後に、外部三角形の頂点を削除 result.removePoint(index1); result.removePoint(index2); result.removePoint(index3); return result; }
//特定の三角形から始めて、周辺の四角形をフリップすることで分割形状を最適化する。 private static void optimizePolygonSeparate(LDPointList form, LDTriangle firstTriangle, LDTriangleList triangles) { LDIndexLineList uncheckedLines = new LDIndexLineList(); uncheckedLines.Add(firstTriangle.getLine1()); uncheckedLines.Add(firstTriangle.getLine2()); uncheckedLines.Add(firstTriangle.getLine3()); //A2-2) スタックSが空になるまで以下を繰り返す while (uncheckedLines.size() != 0) { //A2-2-1) スタックSの一番上のedgeをpopする.これを辺ABとする LDIndexLine lineAB = uncheckedLines.Last(); uncheckedLines.RemoveAt(uncheckedLines.Count - 1); //線と接する2つの三角形を取得 LDTriangleList relatedTriangles = triangles.find(lineAB); //外周はチェックしない if (relatedTriangles.size() == 1) continue; //三角形がダブってるのは不正。隣接0もなにかおかしい Debug.Assert(relatedTriangles.size() == 2); //A2-2-2) 辺ABを含む2個の三角形をABCとABDとする // if(三角形ABCの外接円内にDが入 る) 辺ABをflipし,辺AD/DB/BC/CAをスタックSにpushする //else 何もしない LDTriangle triangleABC = relatedTriangles.at(0); LDTriangle triangleABD = relatedTriangles.at(1); int index = triangleABD.getIndexWithoutLine(lineAB); Debug.Assert(form.length() > index); LDPoint pd = form[index]; // 外接円を求める LDCircle c = LDCircle.getCircumscribedCirclesOfTriangle(form, triangleABC); double dist = PointUtil.distance(c.center, pd); //誤差の範囲ならフリップしない if (dist < c.radius && Math.Abs(c.radius - dist) > 0.00001) { //不正な辺 uncheckedLines.AddRange(flipTriangles(triangleABC, triangleABD, lineAB, triangles)); } } }
public LDPointList transform(LDPointList points, bool clip = false) { LDPointList result=new LDPointList(); int length = points.length(); for (int i = 0; i < length; i++) { result.Add(transform(points[i], clip)); } return result; }
public void setForm(LDPointList value) { Debug.Assert(getPointCount() == value.length()); for (int i = 0; i < getRow() + 1; ++i) { for (int j = 0; j < getColumn() + 1; ++j) { m_gridPoints[i][j] = value[i * (getColumn() + 1) + j]; } } clearBoundsCache(); }
public LDPolygon toPolygon(LDPointList points) { Debug.Assert((points.length() > m_index1)); Debug.Assert(points.length() > m_index2); Debug.Assert(points.length() > m_index3); LDPolygon v = new LDPolygon(); v.Add(points.at(m_index1)); v.Add(points.at(m_index2)); v.Add(points.at(m_index3)); return new LDPolygon(v); }
public void setClockWise(LDPointList form, ClockWise clockWise) { Debug.Assert(form.length() > m_index1); Debug.Assert(form.length() > m_index2); Debug.Assert(form.length() > m_index3); LDPoint v0 = form.at(m_index1); LDPoint v1 = form.at(m_index2); LDPoint v2 = form.at(m_index3); //行列式で時計回りか判定 //行列式の計算。 QMatrix3x3にはないので手動で作成。 double[,] m = new double[3, 3]{{ v0.x(),v0.y(),1 }, { v1.x(),v1.y(),1 }, { v2.x(),v2.y(),1 }}; double determinant = m[0, 0] * m[1, 1] * m[2, 2] + m[0, 1] * m[1, 2] * m[2, 0] + m[0, 2] * m[1, 0] * m[2, 1] - m[0, 2] * m[1, 1] * m[2, 0] - m[0, 0] * m[1, 2] * m[2, 1] - m[0, 1] * m[1, 0] * m[2, 2]; ClockWise current; if (determinant < 0) //CW { current = ClockWise.CW; } else //CCWまたは3点が一直線上など { current = ClockWise.CCW; } if (clockWise != current) //設定した順番と異なる場合 Indexを入れ替える { var p = m_index1; m_index1 = m_index2; m_index2 = p; } }
public void replacePointList(LDPointList form) { Debug.Assert(m_points.length() == form.length()); for (int i = 0; i < form.length(); ++i) { m_points.replace(i, form[i]); } }
public LDLine toLine(LDPointList form) { Debug.Assert(form.length() > m_index1); Debug.Assert(form.length() > m_index2); return new LDLine(form.at(m_index1), form.at(m_index2)); }