private void AddPtToPipePositionList(XYZ xyz) { if (PipePositionList.Count > 0) { pipeHorizontalLength += PipePositionList.Last().Position2d.GetDistanceTo(xyz.Position2d); } PipePositionList.Add(xyz); }
//private bool joinedEdge = false;//test public void CalcPipePosition(Transaction tr, ObjectId tinSurfId, double defaultDepth, bool sameDepthEveryPt, BlockTableRecord ms) { //Нужно учитывать размеры колодцев при расчете положения ребра! //Колодцы бывают просто цилиндрические и просто коробчатые //Учитывать Rotation, BoundingShape, InnerDiameterOrWidth, InnerLength //Уточнить кривую в плане по которой идет труба с учетом размеров колодца //TODO: Как учесть, что блок прямоугольного колодца может не соответствовать колодцу по направлениям длины и ширины???? PointOnCurve2d startSplitPt = null; PointOnCurve2d endSplitPt = null; CivilDB.Structure strStart = null; CivilDB.Structure strEnd = null; if (!StartNode.StructId.IsNull) { strStart = (CivilDB.Structure)tr.GetObject(StartNode.StructId, OpenMode.ForRead); //уточнить положение начала кривой в начале с учетом размеров колодца! startSplitPt = GetSplitPt(strStart, true); } if (!EndNode.StructId.IsNull) { strEnd = (CivilDB.Structure)tr.GetObject(EndNode.StructId, OpenMode.ForRead); //уточнить положение конца кривой в начале с учетом размеров колодца! endSplitPt = GetSplitPt(strEnd, false); } if (startSplitPt != null && endSplitPt != null && startSplitPt.Parameter >= endSplitPt.Parameter) { //колодцы стоят вплотную друг к другу или залезают друг на друга. Места для трубы на остается return; } //проход по составляющим кривой с отбрасыванием частей, отсекаемых колодцами //Curve2d.GetSplitCurves работает неправильно //Curve2d.Explode тоже не помогает if (startSplitPt == null) { AddPtToPipePositionList(new XYZ(PositionCurve.StartPoint)); } Curve2d[] segments = PositionCurve.GetCurves(); double currParam = 0; foreach (Curve2d seg in segments) { Interval interval = seg.GetInterval(); double len = seg.GetLength(interval.LowerBound, interval.UpperBound); currParam += len; //Если есть точка разбиения в начале и она еще не достигнута if (startSplitPt != null) { if (startSplitPt.Parameter < currParam) { //точка разбиения находится на этой кривой. Ее нужно добавить в список AddPtToPipePositionList(new XYZ(startSplitPt.Point)); startSplitPt = null; } else { //точка отсечения начала еще не достигнута, переход к следующей кривой continue; } } if (endSplitPt != null && endSplitPt.Parameter < currParam) { //точка разбиения находится на этой кривой. Ее нужно добавить в список AddPtToPipePositionList(new XYZ(endSplitPt.Point)); endSplitPt = null; break;//обход точек заканчивается } AddPtToPipePositionList(new XYZ(seg.EndPoint)); } //Задание глубин заложения ребер по концам //- если не задана глубина заложения на одном из концов, сделать их равными //- если не задана глубина на обоих концах задать обоим концам глубину по умолчанию согласно вводу в окне CivilDB.TinSurface tinSurf = (CivilDB.TinSurface)tr.GetObject(tinSurfId, OpenMode.ForRead); double startElevByData = double.NegativeInfinity; double endElevByData = double.NegativeInfinity; if (StartPipeJunctionData != null && StartPipeJunctionData.JunctionLevel != double.NegativeInfinity) { startElevByData = StartPipeJunctionData.JunctionLevel; XYZ xyz = PipePositionList.First(); xyz.Z = startElevByData; } if (EndPipeJunctionData != null && EndPipeJunctionData.JunctionLevel != double.NegativeInfinity) { endElevByData = EndPipeJunctionData.JunctionLevel; XYZ xyz = PipePositionList.Last(); xyz.Z = endElevByData; } if (startElevByData != double.NegativeInfinity && endElevByData == double.NegativeInfinity) { XYZ xyz = PipePositionList.Last(); xyz.Z = startElevByData; } else if (startElevByData == double.NegativeInfinity && endElevByData != double.NegativeInfinity) { XYZ xyz = PipePositionList.First(); xyz.Z = endElevByData; } else if (startElevByData == double.NegativeInfinity && endElevByData == double.NegativeInfinity) { XYZ xyz1 = PipePositionList.First(); SetElevBySurf(defaultDepth, tinSurf, xyz1); XYZ xyz2 = PipePositionList.Last(); SetElevBySurf(defaultDepth, tinSurf, xyz2); } //- но не допускать, чтобы труба опускалась ниже дна колодца double sartElevByStr = double.NegativeInfinity; double endElevByStr = double.NegativeInfinity; if (strStart != null && strStart.SumpElevation > PipePositionList.First().Z) { sartElevByStr = strStart.SumpElevation; PipePositionList.First().Z = sartElevByStr; } if (strEnd != null && strEnd.SumpElevation > PipePositionList.Last().Z) { endElevByStr = strEnd.SumpElevation; PipePositionList.Last().Z = endElevByStr; } //после корректировки уточнить отметку соседней точки если по ней нет данных if (sartElevByStr != double.NegativeInfinity && endElevByData == double.NegativeInfinity) { XYZ xyz = PipePositionList.Last(); xyz.Z = sartElevByStr; } else if (startElevByData == double.NegativeInfinity && endElevByStr != double.NegativeInfinity) { XYZ xyz = PipePositionList.First(); xyz.Z = endElevByStr; } //Убедиться, что если в одном узле без колодца стыкуются несколько ребер, //то в месте стыковки обязательно у всех ребер должна быть одинаковая отметка double neighborJunctElev = GetNeigborJuncElev(StartNode); XYZ startPos = PipePositionList.First(); if (neighborJunctElev != double.NegativeInfinity && startPos.Z != neighborJunctElev) { startPos.Z = neighborJunctElev; } neighborJunctElev = GetNeigborJuncElev(EndNode); XYZ endPos = PipePositionList.Last(); if (neighborJunctElev != double.NegativeInfinity && endPos.Z != neighborJunctElev) { endPos.Z = neighborJunctElev; } //Задание отметок промежуточных точек на ребрах сети (интерполяция либо относительно поверхности) if (PipePositionList.Count > 2) { if (sameDepthEveryPt) { //одинаковая глубина относительно поверхности земли //метод TinSurface.SampleElevations работает не так как надо! Он не дает подробного учета рельефа! //точки полилинии for (int i = 1; i < PipePositionList.Count - 1; i++) { XYZ xyz = PipePositionList[i]; SetElevBySurf(defaultDepth, tinSurf, xyz); } //Помимо углов поворотов нужно добавить промежуточные точки через 1 м для учета рельефа! List <XYZ> positionListExtended = new List <XYZ>(); positionListExtended.Add(PipePositionList.First()); for (int i = 1; i < PipePositionList.Count; i++) { XYZ xyz0 = PipePositionList[i - 1]; XYZ xyz1 = PipePositionList[i]; double len = xyz1.Position2d.GetDistanceTo(xyz0.Position2d); Vector2d vector = (xyz1.Position2d - xyz0.Position2d).GetNormal(); double currLen = 1; while (currLen < len) { //добавление промежуточных точек Point2d pt = xyz0.Position2d + vector * currLen; XYZ intermediateXYZ = new XYZ(pt); SetElevBySurf(defaultDepth, tinSurf, intermediateXYZ); positionListExtended.Add(intermediateXYZ); currLen += 1; } positionListExtended.Add(xyz1); } PipePositionList = positionListExtended; } else { //интерполяция между началом и концом double startElev = startPos.Z; double endElev = endPos.Z; double elevDiff = endElev - startElev; double currLength = 0; for (int i = 1; i < PipePositionList.Count - 1; i++) { XYZ xyz = PipePositionList[i]; Point2d prevPt = PipePositionList[i - 1].Position2d; currLength += prevPt.GetDistanceTo(xyz.Position2d); xyz.Z = startElev + (elevDiff * currLength / pipeHorizontalLength); } } } }