private IIlluminationArea CreateIllumShadow(Tuple <Point2d, double> angleStart, Tuple <Point2d, double> angleEnd) { if (angleEnd.Item2 - angleStart.Item2 > Math.PI) { // Переворот начального и конечного угла var t1 = angleEnd; angleEnd = angleStart; angleStart = t1; } // если конечный угол меньше начального расчетного или наоборот, то тень вне границ расчета. Или если начальный угол = конечному if (angleEnd.Item2 < StartAnglesIllum.AngleStartOnPlane || angleStart.Item2 > StartAnglesIllum.AngleEndOnPlane || angleStart.Item2.IsEqual(angleEnd.Item2, 0.001)) { return(null); } if (angleStart.Item2 < StartAnglesIllum.AngleStartOnPlane) { var ptStart = IllumAreaBase.GetPointInRayFromPoint(ptCalc2d, angleStart.Item1, StartAnglesIllum.AngleStartOnPlane); angleStart = new Tuple <Point2d, double>(ptStart, StartAnglesIllum.AngleStartOnPlane); } if (angleEnd.Item2 > StartAnglesIllum.AngleEndOnPlane) { var ptEnd = IllumAreaBase.GetPointInRayFromPoint(ptCalc2d, angleEnd.Item1, StartAnglesIllum.AngleEndOnPlane); angleEnd = new Tuple <Point2d, double>(ptEnd, StartAnglesIllum.AngleEndOnPlane); } var ilum = new IllumAreaCentral(insPt, ptCalc2d, angleStart.Item2, angleEnd.Item2, angleStart.Item1, angleEnd.Item1); return(ilum); }
///// <summary> ///// Построение контура освещенности ///// </summary> //public override void Create (BlockTableRecord space) //{ // Point2d pt1 = Point2d.Origin; // Point2d pt2 = Point2d.Origin; // //Low = CreatePl(insService.Options.VisualOptions[0].Height, // // Color.FromColor(insService.Options.VisualOptions[0].Color), true, ref pt1, ref pt2); // //Medium = CreatePl(insService.Options.VisualOptions[1].Height, // // Color.FromColor(insService.Options.VisualOptions[1].Color), false, ref pt1, ref pt2); // //Hight = CreatePl(insService.Options.VisualOptions[2].Height, // // Color.FromColor(insService.Options.VisualOptions[2].Color), false, ref pt1, ref pt2); // Transaction t = space.Database.TransactionManager.TopTransaction; // visualPl(Low, space, t); // visualPl(Medium, space, t); // visualPl(Hight, space, t); //} public static List <IIlluminationArea> Invert(List <IIlluminationArea> illums, IIlluminationArea startAnglesIllumBound, Point2d ptOrig, IInsPoint insPoint) { double angleStart = startAnglesIllumBound.AngleStartOnPlane; double angleEnd = startAnglesIllumBound.AngleEndOnPlane; List <IIlluminationArea> inverts = new List <IIlluminationArea>(); if (illums.Count == 0) { // Зон теней нет. От стартового угла до конечного - зона освещена var illum = new IllumAreaCentral(insPoint, ptOrig, angleStart, angleEnd, GetPointInRayByLength(ptOrig, angleStart, 50), GetPointInRayByLength(ptOrig, angleEnd, 50)); inverts.Add(illum); } else { double curStart = angleStart; Point2d cusStartPt = GetPointInRayFromPoint(illums[0].PtOrig, illums[0].PtStart, curStart); foreach (var item in illums) { if (item.AngleStartOnPlane - curStart > 0.01) { var illum = new IllumAreaCentral(insPoint, item.PtOrig, curStart, item.AngleStartOnPlane, cusStartPt, item.PtStart); inverts.Add(illum); } curStart = item.AngleEndOnPlane; cusStartPt = item.PtEnd; } if (angleEnd - curStart > 0.1) { Point2d ptEnd = GetPointInRayFromPoint(illums[0].PtOrig, cusStartPt, angleEnd); var illum = new IllumAreaCentral(insPoint, illums[0].PtOrig, curStart, angleEnd, cusStartPt, ptEnd); inverts.Add(illum); } } return(inverts); }
public List <IIlluminationArea> Calc() { var resAreas = new List <IIlluminationArea>(); // Корректировка расчетной точки if (!CorrectCalcPoint()) { return(null); } // Проверка - если точка расположена внутри другого дома (кроме собственного), то вся точка в тени if (IsCalcPointInsideOtherBuilding()) { throw new Exception("Расчтеная точка попадает на соседнее здание."); //return null; } // Определение ограничений углов (начального и конечного) с учетом плоскости стены расчетного дома if (DefineStartAnglesByOwnerBuilding()) { // расчетные граници (по заданным расчетным углам) var ext = GetCalcExtents(map.MaxBuildingHeight); // кусок карты using (var scope = map.GetScope(ext)) { // исключение из списка домов собственно расчетного дома if (buildingOwner != null) { scope.Buildings.Remove(buildingOwner); } // Добавление отсеченных частей здания от собственного здания расчетной точки if (secantBuildings != null) { foreach (var item in secantBuildings) { item.InitContour(); } scope.Buildings.AddRange(secantBuildings); } // Расчет зон теней // группировка домов по высоте var heights = scope.Buildings.GroupBy(g => g.HeightCalc); double ptHeightCalc = GetPtCalcHeight(); foreach (var bHeight in heights) { double heightCalc = GetHeightCalcBuilding(ptHeightCalc, bHeight.Key); if (heightCalc == 0) { continue; } var illumsByHeight = CalcIllumsByHeight(bHeight.ToList(), heightCalc); if (illumsByHeight != null && illumsByHeight.Any()) { resAreas.AddRange(illumsByHeight); } } } resAreas = IllumAreaBase.Merge(resAreas); // Инвертировать зоны теней в зоны освещенностей resAreas = IllumAreaCentral.Invert(resAreas, StartAnglesIllum, ptCalc2d, insPt); } else { StartAnglesIllum.AngleEndOnPlane = 0; StartAnglesIllum.AngleStartOnPlane = 0; } return(resAreas); }