private List <IIlluminationArea> CalcIllumsByHeight(List <MapBuilding> buildings, double height) { List <IIlluminationArea> illumShadows = new List <IIlluminationArea>(); using (Line lineShadow = GetLineShadow(height)) { // перебор домов одной высоты foreach (var build in buildings) { // Если дом полностью выше линии тени (сечения), то он полностью затеняет точку if (build.YMin >= (lineShadow.StartPoint.Y - 0.1)) { // Найти точку начала тени и конца (с минимальным и макс углом к точке расчета) var ilumShadow = GetBuildingZeroLineShadows(build); //var ilumShadow = GetIllumShadow(build.Contour.GetPoints().Where(p=>p.Y<ptCalc.Y).ToList()); if (ilumShadow != null) { illumShadows.Add(ilumShadow); } } else if (build.YMax >= (lineShadow.StartPoint.Y - 0.1)) { var ilumsBoundary = GetBuildingLineShadowBoundary(build, lineShadow, Intersect.ExtendThis); illumShadows.AddRange(ilumsBoundary); } } #if TEST EntityHelper.AddEntityToCurrentSpace(lineShadow); #endif } // Объединение совпадающих зон теней illumShadows = IllumAreaBase.Merge(illumShadows); return(illumShadows); }
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); }