//与えられた点群すべてを含む矩形を取得 public static LDRect getBoundingRect(LDPointList form) { float maxX = float.MinValue; float minX = float.MaxValue; float maxY = float.MinValue; float minY = float.MaxValue; foreach (var p in form) { float x = p.x(); float y = p.y(); if (x < minX) { minX = x; // 最小のx } if (x > maxX) { maxX = x; // 最大のx } if (y < minY) { minY = y; // 最小のy } if (y > maxY) { maxY = y; // 最大のy } } LDRect rect = new LDRect(); rect.setLeft(minX); rect.setRight(maxX); rect.setTop(minY); rect.setBottom(maxY); return rect; }
/* public void serializeTest() { const char* name = "lineList"; QSharedPointer<LDIndexLineList> src(new LDIndexLineList); src->push_back(LDIndexLine(0, 1)); //シリアライズ SerializeHelper::writeBoostXml(name, src); //デシリアライズ auto dst = SerializeHelper::readBoostXml<LDIndexLineList>(name); QVERIFY(*(dst.data()) == *(src.data())); } */ public void hitTest() { LDIndexLineList lines = new LDIndexLineList(); LDIndexLine line_1 = new LDIndexLine(0, 1); LDIndexLine line_2 = new LDIndexLine(1, 2); LDIndexLine line_3 = new LDIndexLine(2, 3); LDIndexLine line_4 = new LDIndexLine(3, 0); lines.add(line_1); lines.add(line_2); lines.add(line_3); lines.add(line_4); LDPointList points = new LDPointList(); points.Add(new LDPoint(0, 0)); points.Add(new LDPoint(100, 0)); points.Add(new LDPoint(100, 100)); points.Add(new LDPoint(0, 100)); TestUtil.COMPARE(lines.isHit(points, new LDPoint(0, 0), 1), true);//頂点上 TestUtil.COMPARE(lines.isHit(points, new LDPoint(50, 0), 1), true);//線上 TestUtil.COMPARE(lines.isHit(points, new LDPoint(50, 1), 3), true);//線からちょっと離れたところ TestUtil.COMPARE(lines.isHit(points, new LDPoint(50, 4), 3), false);//線から範囲外に離れたところ TestUtil.COMPARE(lines.isHit(points, new LDPoint(200, 0), 3), false);//線の延長戦上に離れたところ TestUtil.COMPARE(lines.isHit(points, new LDPoint(200, 1), 3), false);//線の延長戦上に離れたところ }
} // static LDTriangleList exec(LDPointList form,LDIndexLineList limitedLines);//TODO ,LDProgress progress private static void triangulationFromPoint(LDPointList form, LDPoint p, LDTriangleList triangles) { // A2-1) piを含む三角形ABCを発見し, この三角形をAB pi, BC pi, CA pi の3個の三角形に分割. // この時, 辺AB, BC, CAをスタックSに積む (最初の一点のときには,super triangleが見つかる) for (int i = 0; i < triangles.length();) { LDTriangle t = triangles[i]; if (!TriangleUtil.containsPoint(t.toPolygon(form), p)) { //対象の三角形の外側なら次へ i++; continue; } // 古い三角形をリストから削除して、分割した三角形を追加 triangles.RemoveAll(item => item == t); int index = form.IndexOf(p); Debug.Assert(index >= 0); triangles.Add(new LDTriangle(index, t.getIndex1(), t.getIndex2())); triangles.Add(new LDTriangle(index, t.getIndex2(), t.getIndex3())); triangles.Add(new LDTriangle(index, t.getIndex3(), t.getIndex1())); //TODO すでにある線分で制限する機能が未移植 // if ( limitLineList.size() != 0 ) // { // flipCheckWithLimit( t.p1, t.p2, t.p3 , pg ); // } // else // { optimizePolygonSeparate(form, t, triangles); // } } }
public LDPointList getPointList() { LDPointList result=new LDPointList(); result.Add(m_topLeft); result.Add(m_topRight); result.Add(m_bottomRight); result.Add(m_bottomLeft); return result; }
public void triangulationTest() { { //0個の頂点を分割。0個の三角形を取得 LDPointList form = new LDPointList(); LDTriangleList result = Triangulation.exec(form); TestUtil.COMPARE(result.length(), 0); } { //1個の頂点を分割。0個の三角形を取得 LDPointList form = new LDPointList(); form.add(new LDPoint(0, 0)); LDTriangleList result = Triangulation.exec(form); TestUtil.COMPARE(result.length(), 0); } { //2個の頂点を分割。0個の三角形を取得 LDPointList form = new LDPointList(); form.add(new LDPoint(0, 0)).add(new LDPoint(1, 1)); LDTriangleList result = Triangulation.exec(form); TestUtil.COMPARE(result.length(), 0); } { //3個の頂点を分割。1個の三角形を取得 LDPointList form = new LDPointList(); form.add(new LDPoint(0, 0)).add(new LDPoint(1, 1)).add(new LDPoint(1, 0)); LDTriangleList result = Triangulation.exec(form); TestUtil.COMPARE(result.length(), 1); TestUtil.VERIFY(result[0] == new LDTriangle(0, 1, 2)); } { //4個の頂点を分割。2個の三角形を取得 LDPointList form = new LDPointList(); form.add(new LDPoint(0, 0)).add(new LDPoint(1, 1)).add(new LDPoint(1, 0)).add(new LDPoint(0, 1)); LDTriangleList result = Triangulation.exec(form); TestUtil.COMPARE(result.length(), 2); TestUtil.VERIFY(result.Contains(new LDTriangle(0, 1, 2))); TestUtil.VERIFY(result.Contains(new LDTriangle(0, 1, 3))); } // { // LDPointList form; // form).add( new LDPoint(20,0)).add( new LDPoint(1,1)).add( new LDPoint(1,0)).add( new LDPoint(0,1) // ).add( new LDPoint(0,15.5)).add( new LDPoint(11,12)).add( new LDPoint(1,0)).add( new LDPoint(100,0.1); // LDTriangleList result=Triangulation.exec(form); // qDebug()).add( new result; // } }
public void getOutlinePointsTest_simple() { LDTriangleList triangles = simpleTriangle(); LDPointList points=new LDPointList(); points.Add(new LDPoint(0, 0)); points.Add(new LDPoint(0, 100)); points.Add(new LDPoint(100, 100)); LDPointList compare = points; LDPointList result = triangles.getOutlinePoints(points); TestUtil.COMPARE(result, compare); }
//特定の三角形から始めて、周辺の四角形をフリップすることで分割形状を最適化する。 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)); } } }
//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; }
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
public void getOutlinePointIndicesTest_simple() { LDTriangleList triangles = simpleTriangle(); LDPointList points=new LDPointList(); points.Add(new LDPoint(0, 0)); points.Add(new LDPoint(0, 100)); points.Add(new LDPoint(100, 100)); List<int> compare=new List<int>(); compare.Add(0); compare.Add(1); compare.Add(2); List<int> result = triangles.getOutlinePointIndices(points); TestUtil.COMPARELIST(result, compare); }
//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; }
// 三角形を与えてその外接円を求める public static LDCircle getCircumscribedCirclesOfTriangle(LDPointList form, LDTriangle t) { // 三角形の各頂点座標を (x1, y1), (x2, y2), (x3, y3) とし、 // その外接円の中心座標を (x, y) とすると、 // (x - x1) * (x - x1) + (y - y1) * (y - y1) // = (x - x2) * (x - x2) + (y - y2) * (y - y2) // = (x - x3) * (x - x3) + (y - y3) * (y - y3) // より、以下の式が成り立つ // // x = { (y3 - y1) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) // + (y1 - y2) * (x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1)} / c // // y = { (x1 - x3) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) // + (x2 - x1) * (x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1)} / c // // ただし、 // c = 2 * {(x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1)} LDPoint p1 = t.getPoint1(form); LDPoint p2 = t.getPoint2(form); LDPoint p3 = t.getPoint3(form); float x1 = (float)p1.x(); float y1 = (float)p1.y(); float x2 = (float)p2.x(); float y2 = (float)p2.y(); float x3 = (float)p3.x(); float y3 = (float)p3.y(); float c = 2.0f * ((x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1)); float x = ((y3 - y1) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) + (y1 - y2) * (x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1)) / c; float y = ((x1 - x3) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) + (x2 - x1) * (x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1)) / c; LDPoint center = new LDPoint(x, y); // 外接円の半径 r は、半径から三角形の任意の頂点までの距離に等しい double r = math.PointUtil.distance(center, p1); return new LDCircle(center, (float)r); }
//与えられた点群すべてを含む矩形を取得 public static LDRect getBoundingRect(LDPointList form) { float maxX = float.MinValue; float minX = float.MaxValue; float maxY = float.MinValue; float minY = float.MaxValue; foreach (var p in form) { float x = p.x(); float y = p.y(); if (x < minX) { minX = x; // 最小のx } if (x > maxX) { maxX = x; // 最大のx } if (y < minY) { minY = y; // 最小のy } if (y > maxY) { maxY = y; // 最大のy } } LDRect rect = new LDRect(); rect.setLeft(minX); rect.setRight(maxX); rect.setTop(minY); rect.setBottom(maxY); return(rect); }
public void simpleTransformTest() { LDQuadTransform quad=new LDQuadTransform(new LDPoint(10, 10), new LDPoint(30, 30)); { LDPoint src=new LDPoint(0, 0); LDPoint dst; dst = quad.transform(src); TestUtil.COMPARE(dst.x(), 10.0); TestUtil.COMPARE(dst.y(), 10.0); } { LDPoint src=new LDPoint(1, 1); LDPoint dst; dst = quad.transform(src); TestUtil.COMPARE(dst.x(), 30.0); TestUtil.COMPARE(dst.y(), 30.0); } { LDPoint src=new LDPoint(0.5f, 0.25f); LDPoint dst; dst = quad.transform(src); TestUtil.COMPARE(dst.x(), 20.0f); TestUtil.COMPARE(dst.y(), 15.0f); } { LDPoint src=new LDPoint(0.75f, 0.8f); LDPoint dst; dst = quad.transform(src); TestUtil.COMPARE(dst.x(), 25.0f); TestUtil.COMPARE(dst.y(), 26.0f); } { LDPointList src=new LDPointList(); src.add(new LDPoint(0.25f, 0.4f)).add( new LDPoint(0.75f, 0.8f)); LDPointList dst; dst = quad.transform(src); TestUtil.VERIFY(dst.length() == 2); TestUtil.COMPARE(dst[0],new LDPoint(15.0f, 18.0f)); TestUtil.COMPARE(dst[1],new LDPoint(25, 26)); } // { // LDGridTransform src(0.5,0.5,0.5,0.5,1,1); // LDGridTransform dst; // dst=grid.transform(src); // TestUtil.COMPARE(dst.getPoint(0,0),LDPoint(40,40)); // TestUtil.COMPARE(dst.getPoint(0,1),LDPoint(60,40)); // TestUtil.COMPARE(dst.getPoint(1,1),LDPoint(60,60)); // TestUtil.COMPARE(dst.getPoint(1,0),LDPoint(40,60)); // } // { // LDAffineTransform src; // src.translate(0.5,0.5); // src.rotate(30); // src.scale(2,2); // LDAffineTransform dst; // dst=grid.transform(src); // TestUtil.COMPARE(dst.getTranslate(),LDPoint(40,40)); // } }
/* public void serializeTest() { string name = "gridMesh"; LDGridTransform src = new LDGridTransform(0, 0, 100, 100, 2, 2)); //シリアライズ SerializeHelper.writeBoostXml(name, src); //デシリアライズ var dst = SerializeHelper.readBoostXml<LDGridTransform>(name); TestUtil.VERIFY(dst->getGridPoints() == src->getGridPoints()); } */ public void simpleTransformTest() { LDGridTransform grid = new LDGridTransform(20, 20, 40, 40, 1, 1); { LDPoint src = new LDPoint(0.5f, 0.5f); LDPoint dst; dst = grid.transform(src); TestUtil.COMPARE(dst.x(), 40.0); TestUtil.COMPARE(dst.y(), 40.0); } { LDPointList src = new LDPointList(); src.add(new LDPoint(0.25f, 0.25f)).add(new LDPoint(0.75f, 0.75f)); LDPointList dst; dst = grid.transform(src); TestUtil.VERIFY(dst.length() == 2); TestUtil.COMPARE(dst[0], new LDPoint(30.0f, 30)); TestUtil.COMPARE(dst[1], new LDPoint(50.0f, 50)); } { LDGridTransform src = new LDGridTransform(0.5f, 0.5f, 0.5f, 0.5f, 1, 1); LDGridTransform dst = new LDGridTransform(); dst = grid.transform(src); TestUtil.COMPARE(dst.getPoint(0, 0),new LDPoint(40, 40)); TestUtil.COMPARE(dst.getPoint(0, 1),new LDPoint(60, 40)); TestUtil.COMPARE(dst.getPoint(1, 1),new LDPoint(60, 60)); TestUtil.COMPARE(dst.getPoint(1, 0),new LDPoint(40, 60)); } { LDAffineTransform src = new LDAffineTransform(); src.translate(0.5f, 0.5f); src.rotate(30); src.scale(2, 2); LDAffineTransform dst = new LDAffineTransform(); dst = grid.transform(src); TestUtil.COMPARE(dst.getTranslate(), new LDPoint(40, 40)); } }
public void inverseTransformTest() { { LDGridTransform grid = new LDGridTransform(20, 20, 40, 40, 2, 2); LDPoint src = new LDPoint(30, 30); LDPoint dst = new LDPoint(); dst = grid.inverseTransform(src); TestUtil.COMPARE(dst.x(), 0.25); TestUtil.COMPARE(dst.y(), 0.25); } { LDGridTransform grid = new LDGridTransform(20, 20, 40, 40, 2, 2); LDPointList src = new LDPointList(); src.add(new LDPoint(30, 30)).add(new LDPoint(50, 50)); LDPointList dst; dst = grid.inverseTransform(src); TestUtil.COMPARE(dst[0], new LDPoint(0.25f, 0.25f)); TestUtil.COMPARE(dst[1], new LDPoint(0.75f, 0.75f)); } /* { LDGridTransform grid = new LDGridTransform(20, 20, 40, 40, 2, 2); LDGridTransform src = new LDGridTransform(24, 24, 52 - 24, 52 - 24, 2, 2); LDGridTransform dst = src; var points = grid.inverseTransform(src.toForm()); dst.setForm(points); LDFUZZY_COMPARE(dst.getPoint(0, 0).x(), 0.1f, 0.0000001f); LDFUZZY_COMPARE(dst.getPoint(2, 2).x(), 0.8f, 0.0000001f); LDFUZZY_COMPARE(dst.getPoint(2, 0).x(), 0.1f, 0.0000001f); LDFUZZY_COMPARE(dst.getPoint(2, 0).y(), 0.8f, 0.0000001f); } */ { LDGridTransform grid = new LDGridTransform(20.53125f, 20.62423f, 40.614312f, 40.94645f, 2, 2); LDGridTransform src = new LDGridTransform(24.0134623f, 24.9143f, 52 - 24.090023f, 52 - 24.00001f, 2, 2); LDGridTransform dst = new LDGridTransform(src); var points = grid.inverseTransform(src.toForm()); var rest = grid.transform(points); dst.setForm(points); TestUtil.VERIFY(LDMathUtil.fuzzyCompare(rest, src.toForm(), 0.0000001f)); } { LDGridTransform grid=new LDGridTransform(2530.53125f, 2540.62423f, 4015.614312f, 4026.94645f, 2, 2); LDGridTransform src=new LDGridTransform(2594.0134623f, 2594.9143f, 5274 - 2594.090023f, 5276 - 2594.00001f, 2, 2); LDGridTransform dst = new LDGridTransform( src); var points = grid.inverseTransform(src.toForm()); var rest = grid.transform(points); dst.setForm(points); TestUtil.VERIFY(LDMathUtil.fuzzyCompare(rest, src.toForm(), 0.0000001f)); } { LDGridTransform grid=new LDGridTransform( new LDPoint(20.53125f, 20.62423f) , new LDPoint(40.53125f, 20.62423f) , new LDPoint(45.53125f, 45.62423f) , new LDPoint(20.614312f, 40.94645f), 2, 2); LDGridTransform src=new LDGridTransform(34.0134623f, 24.9143f, 52 - 24.090023f, 52 - 24.00001f, 8, 8); LDGridTransform dst = new LDGridTransform(src); var points = grid.inverseTransform(src.toForm()); var rest = grid.transform(points); dst.setForm(points); TestUtil.VERIFY(LDMathUtil.fuzzyCompare(rest, src.toForm(), 0.0000001f)); } { LDGridTransform grid=new LDGridTransform( new LDPoint(2012.53125f, 2051.62423f) , new LDPoint(4097.53125f, 2033.62423f) , new LDPoint(4575.53125f, 4566.62423f) , new LDPoint(2062.614312f, 4000.94645f), 2, 2); LDGridTransform src=new LDGridTransform(3444.0134623f, 2442.9143f, 5242 - 2412.090023f, 5211 - 2467.00001f, 8, 8); LDGridTransform dst = new LDGridTransform(src); var points = grid.inverseTransform(src.toForm()); var rest = grid.transform(points); dst.setForm(points); TestUtil.VERIFY(LDMathUtil.fuzzyCompare(rest, src.toForm(), 0.0000001f)); } }
/// <summary> /// 未実装 /// </summary> /// <param name="form"></param> public void replaceForm(LDPointList form) { throw new NotImplementedException(); }
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 bool isHit(LDPointList form , LDPoint p, float hitRange) { LDLine l = this.toLine(form); LDPoint startPt = l.p1(); LDPoint endPt = l.p2(); //端点から一定の距離内だったら当たり if (PointUtil.isHit(startPt, p, hitRange)) return true; if (PointUtil.isHit(endPt, p, hitRange)) return true; //点が一直線上にないか確認 if (TriangleUtil.isTriangle(startPt, endPt, p)) { //鈍角三角形なら判定外 if (TriangleUtil.isObtuseAngle(startPt, endPt, p)) { return false; } //三角形の面積を算出して、その底面で割れば高さ=線と点の距離 float distance = TriangleUtil.getTriangleHeight(startPt, endPt, p); if (distance <= hitRange) { return true; } return false; } //一直線上にあるが線分外にあるか判定 LDVector2 ab = new LDVector2(endPt - startPt); LDVector2 ap = new LDVector2(p - startPt); LDVector2 bp = new LDVector2(p - endPt); float omega = 0.0001f;//NOTE:誤差の基準値 かなり適当に指定 if (ap.length() + bp.length() > ab.length() + omega) { return false; } return true; }
public LDPoint getPoint3(LDPointList points) { return points[m_index2]; }
public void copyFrom(LDUvMesh src) { m_points = src.m_points; m_uvMap = src.m_uvMap; m_lines = src.m_lines; m_triangles = src.m_triangles; }
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]); } }
private static void triangulationFromPoint(LDPointList form, LDPoint p, LDTriangleList triangles) { // A2-1) piを含む三角形ABCを発見し, この三角形をAB pi, BC pi, CA pi の3個の三角形に分割. // この時, 辺AB, BC, CAをスタックSに積む (最初の一点のときには,super triangleが見つかる) for (int i = 0; i < triangles.length();) { LDTriangle t = triangles[i]; if (!TriangleUtil.containsPoint(t.toPolygon(form), p)) { //対象の三角形の外側なら次へ i++; continue; } // 古い三角形をリストから削除して、分割した三角形を追加 triangles.RemoveAll(item => item == t); int index = form.IndexOf(p); Debug.Assert(index >= 0); triangles.Add(new LDTriangle(index, t.getIndex1(), t.getIndex2())); triangles.Add(new LDTriangle(index, t.getIndex2(), t.getIndex3())); triangles.Add(new LDTriangle(index, t.getIndex3(), t.getIndex1())); //TODO すでにある線分で制限する機能が未移植 // if ( limitLineList.size() != 0 ) // { // flipCheckWithLimit( t.p1, t.p2, t.p3 , pg ); // } // else // { optimizePolygonSeparate(form, t, triangles); // } } }
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 static LDPolygon getHugeTriangle(LDPointList form) { return getHugeTriangle(PointUtil.getBoundingRect(form)); }
public LDPointList toForm() { LDPointList result = new LDPointList(); for (int i = 0; i < getRow() + 1; ++i) { for (int j = 0; j < getColumn() + 1; ++j) { result.Add(m_gridPoints[i][j]); } } return result; }
public LDPointList inverseTransform(LDPointList points) { LDPointList result= new LDPointList(); foreach (var pt in points) { result.Add(inverseTransform(pt)); } return result; }
public LDPoint getPoint1(LDPointList points) { return points[m_index1]; }
//特定の三角形から始めて、周辺の四角形をフリップすることで分割形状を最適化する。 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 getOutlinePoints() { List<int> indices = getOutlinePointIndices(); LDPointList result = new LDPointList(); foreach (var index in indices) { result.Add(getPoint(index)); } return result; }
// 点群を包含する十分大きな正三角形を求める public static LDPolygon getHugeTriangle(LDPointList form) { return(getHugeTriangle(PointUtil.getBoundingRect(form))); }
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 LDPointList transform(LDPointList form) { LDPointList result= new LDPointList(); foreach (var pt in form) { result.Add(transform(pt)); } return result; }
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)); }