/// <summary> /// 平面での線と点の位置関係 /// ・| /// |・ /// /// 点p1 - 点p2 を結ぶ線分の左右どちらに 点q があるか? /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="q"></param> /// <returns></returns> public static double OnSeg(Pnt p1, Pnt p2, Pnt q) { double vx1 = p2.X - p1.X; double vy1 = p2.Y - p1.Y; double vx2 = q.X - p1.X; double vy2 = q.Y - p1.Y; double ans = vx1 * vy2 - vy1 * vx2; return(ans); }
/// <summary> /// 四角形の対角線とある線分の延長上で交わる場合の交点を求めます。 /// </summary> /// <param name="p0">対角線の点P0</param> /// <param name="p1">対角線の点P1</param> /// <param name="p2">メッシュの中心の点P2</param> /// <param name="p3">対角線と向かい合う点P3</param> /// <param name="p">P0-P1とP2-P3の交点</param> /// <returns>四角形の対角線とある線分の延長上で交わる場合、真</returns> public static bool Intersection(Pnt p0, Pnt p1, Pnt p2, Pnt p3, out Pnt p) { p = null; double s, t; /* * +---+---+---+ * | /| * - + / + * | * / | * + / * + + * | / | * +---+---+---+ */ //s = (p0.X - p1.X) * (p2.Y - p0.Y) + (p0.Y - p1.Y) * (p0.X - p2.X); //t = (p0.X - p1.X) * (p3.Y - p0.Y) + (p0.Y - p1.Y) * (p0.X - p3.X); //if (s * t >= 0) // return false; s = (p2.X - p3.X) * (p0.Y - p2.Y) + (p2.Y - p3.Y) * (p2.X - p0.X); t = (p2.X - p3.X) * (p1.Y - p2.Y) + (p2.Y - p3.Y) * (p2.X - p1.X); if (s * t >= 0) { return(false); } // 線分が重なっている場合、交差していない // 線分の先端が触れている場合、交差していない // 線分が交わって交差した // ついでに交点も求める double a1 = p0.X - p1.X; double b1 = p1.Y - p0.Y; double c1 = (p1.Y - p0.Y) * p0.X - (p1.X - p0.X) * p0.Y; double a2 = p2.X - p3.X; double b2 = p3.Y - p2.Y; double c2 = (p3.Y - p2.Y) * p2.X - (p3.X - p2.X) * p2.Y; //double x = (c1 * b2 - c2 * b1) / (a1 * b2 - a2 * b1); //double y = (a1 * c2 - a2 * c1) / (a1 * b2 - a2 * b1); double y = (c1 * b2 - c2 * b1) / (a1 * b2 - a2 * b1); double x = (a1 * c2 - a2 * c1) / (a1 * b2 - a2 * b1); p = new Pnt(x, y); return(true); }
public Face(Pnt a, Pnt b, Pnt c) { this.a = a; this.b = b; this.c = c; }
static void Main(string[] args) { Console.WriteLine("■START"); //XMLReader reader = new XMLReader(@"./akt2新工事.xml"); XMLReader reader = new XMLReader(@"./5000かけ5000.xml"); reader.ReadXML("Surfaces"); List <Face> faces = reader.Faces; List <Pnt> pnts = reader.Pnts; //for (int i = 0; i < faces.Count; i++) { // Console.WriteLine($"{faces[i].A.ID} {faces[i].B.ID} {faces[i].C.ID}"); //} // 原点 Pnt origin = new Pnt(0, 0); // 真北を上に // 公共座標で扱っているので縦軸X、横軸Yで考える(数学軸なら縦軸Y、横軸X) double t = Math.Atan2(0 - origin.Y, 1 - origin.X); // 指定したモードの範囲内にラジアンを収める double direction = CoordinateMath.Clamp(2, t); // 範囲を絞るために計画工区に寄せた原点を求めます。 double minX = double.NaN; double minY = double.NaN; double localX = 0.0D; double localY = 0.0D; int pntCount = pnts.Count; for (int i = 0; i < pntCount; i++) { Pnt pnt = pnts[i]; CoordinateMath.ToLocal(pnt.X, pnt.Y, origin.X, origin.Y, -direction, ref localX, ref localY); if ((localX % meshPitch) != 0) { localX -= (localX % meshPitch); localX -= meshPitch; } if ((localY % meshPitch) != 0) { localY -= (localY % meshPitch); localY -= meshPitch; } if (localX < minX || double.IsNaN(minX)) { minX = localX; } if (localY < minY || double.IsNaN(minY)) { minY = localY; } } double originX = 0.0; double originY = 0.0; CoordinateMath.ToPublic(minX, minY, origin.X, origin.Y, -direction, ref originX, ref originY); // 範囲を絞るために計画工区に寄せた原点 Pnt shiftOrigin = new Pnt(originX, originY); // 5000マス×5000マスのメッシュに収まるかチェックします。 double maxX = double.NaN; double maxY = double.NaN; for (int i = 0; i < pnts.Count; i++) { Pnt pnt = pnts[i]; if (pnt.X > maxX || double.IsNaN(maxX)) { maxX = pnt.X; } if (pnt.Y > maxY || double.IsNaN(maxY)) { maxY = pnt.Y; } } // MeshLength * MeshLength に収まっているか // 最も遠い公共座標(単位:m)をマス目換算して 50 / 0.5 = 100 // シフト原点もマス目換算したもので引き算。 // 使用するマス目がメッシュサイズの上限を超えていないかチェック if (meshLength >= maxX / meshPitch - shiftOrigin.X / meshPitch & meshLength >= maxY / meshPitch - shiftOrigin.Y / meshPitch) { Console.WriteLine("inside"); } else { Console.WriteLine($"outside x:{maxX} y:{maxY}"); } var sw = new Stopwatch(); sw.Start(); Console.WriteLine("■深さ計算処理 開始"); PlanDepthArray planDepth = new PlanDepthArray(meshLength, meshPitch, shiftOrigin, pnts, faces); planDepth.Create(); sw.Stop(); Console.WriteLine("■深さ計算処理 にかかった時間"); Console.WriteLine($" {sw.Elapsed}"); Console.WriteLine($" {sw.Elapsed.Hours}時間 {sw.Elapsed.Minutes}分 {sw.Elapsed.Seconds}秒 {sw.Elapsed.Milliseconds}ミリ秒"); Console.WriteLine($" {sw.ElapsedMilliseconds}ミリ秒"); Console.WriteLine("■深さ計算処理 終了"); double seekStartX = 0; double seekStartY = 0; Console.WriteLine("■ファイル出力 START"); int planLength = planDepth.PlanDepths.Length; seekStartX = 0.25 + shiftOrigin.X; seekStartY = 0.25 + shiftOrigin.Y; if (File.Exists("plan.txt")) { File.Delete("plan.txt"); } StreamWriter planWriter = new StreamWriter("plan.txt", true, Encoding.UTF8); for (int i = 0; i < planLength; i++) { int _y = Math.DivRem(i, meshLength, out int _x); try { if (planDepth.PlanDepths[i] == -1) { planWriter.WriteLine($"X:{ seekStartX + _x * meshPitch } Y:{seekStartY + _y * meshPitch} Depth:{planDepth.PlanDepths[i]}"); } else { planWriter.WriteLine($"X:{ seekStartX + _x * meshPitch } Y:{seekStartY + _y * meshPitch} Depth:{planDepth.PlanDepths[i] / 100.0}"); } } catch (Exception e) { Logger.Write(Logger.E, e.ToString()); break; } } planWriter.Close(); Console.WriteLine("■ファイル出力 END"); Console.ReadKey(); }
public void ReadXML(string element) { string retWord = string.Empty; XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(path); XmlElement rootElement = xmlDoc.DocumentElement; // Surfaces XmlNodeList surfaces = rootElement.GetElementsByTagName(element); if (surfaces.Count < 1 | surfaces.Count > 1) { tinPnts = null; tinFaces = null; return; } //Console.WriteLine(surfaces[0].Name); // Surface XmlNodeList surface = surfaces[0].ChildNodes; if (surface.Count < 2 | surface.Count > 2) { tinPnts = null; tinFaces = null; return; } // [0]はアスファルトで敷き均した深さ // [1]が計画の深さに当たる //Console.WriteLine(surface[1].Name); // Definition XmlNodeList definition = surface[1].ChildNodes; if (definition.Count < 1 | definition.Count > 1) { tinPnts = null; tinFaces = null; return; } //Console.WriteLine(definition[0].Name); // Pnts Faces XmlNodeList xmlNodeList = definition[0].ChildNodes; if (xmlNodeList.Count < 2 | xmlNodeList.Count > 2) { tinPnts = null; tinFaces = null; return; } // Pnt XmlNode pnts = xmlNodeList[0]; foreach (XmlNode p in pnts.ChildNodes) { //Console.WriteLine(p.Name); // P //Console.WriteLine(p.Attributes[0].InnerText); //Console.WriteLine(p.InnerText); Pnt pnt = new Pnt( p.Attributes[0].InnerText, double.Parse(p.InnerText.Split(' ')[0]), double.Parse(p.InnerText.Split(' ')[1]), double.Parse(p.InnerText.Split(' ')[2])); tinPnts.Add(pnt); } // faces XmlNode faces = xmlNodeList[1]; foreach (XmlNode f in faces.ChildNodes) { //Console.WriteLine(f.Name); // F //Console.WriteLine(f.InnerText); string pntAID = f.InnerText.Split(' ')[0]; string pntBID = f.InnerText.Split(' ')[1]; string pntCID = f.InnerText.Split(' ')[2]; Pnt a = tinPnts.Where(p => p.ID.Equals(pntAID)).Single(); Pnt b = tinPnts.Where(p => p.ID.Equals(pntBID)).Single(); Pnt c = tinPnts.Where(p => p.ID.Equals(pntCID)).Single(); Face face = new Face(a, b, c); tinFaces.Add(face); } }