Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        ///// <summary>
        ///// Начальный угол в плане (радиан). Начальное значение = 0 - восход.
        ///// Будут определены для этой расвчетной точки индивидуально
        ///// </summary>
        //public double AngleStartOnPlane { get; private set; }
        ///// <summary>
        ///// Конечный угол в плане (радиан). Начальное значение = 180 - заход
        ///// </summary>
        //public double AngleEndOnPlane { get; private set; }

        public CalcPointCentral(InsPoint insPt, CalcServiceCentral insCalcService)
        {
            this.map      = insPt.Model.Map;
            buildingOwner = insPt.Building;
            this.insPt    = insPt;
            ptCalc        = insPt.Point;
            ptCalc2d      = ptCalc.Convert2d();
            this.calc     = insCalcService;
            values        = insCalcService.CalcValues;

            //AngleStartOnPlane = values.SunCalcAngleStartOnPlane;
            //AngleEndOnPlane = values.SunCalcAngleEndOnPlane;
            StartAnglesIllum = new IllumAreaBase(insPt, ptCalc2d, values.SunCalcAngleStartOnPlane, values.SunCalcAngleEndOnPlane,
                                                 Point2d.Origin, Point2d.Origin);
        }
Exemple #4
0
        /// <summary>
        /// Корректировка стартовых углов инсоляции от расчетной точки которая находится на вершине полилинии контура здания
        /// </summary>
        /// <param name="vertexIndex">Индекс вершины - расчетной точки</param>
        private void CorrectStartAnglesByOwnerCorner(int vertexIndex)
        {
            var contour   = buildingOwner.Contour;
            var nextIndex = contour.NextVertexIndex(vertexIndex, -1);
            var seg       = contour.GetLineSegment2dAt(vertexIndex);
            var segNext   = contour.GetLineSegment2dAt(nextIndex);
            // Область освещения от угла контура - от 1 сегмента до 2 (угол вне дома)
            var cornerIllum = new IllumAreaBase(insPt, ptCalc2d, seg.Direction.Angle, segNext.Direction.Negate().Angle, Point2d.Origin, Point2d.Origin);

            // Проверка - если средний вектор внутри здания, то инвертировать область
            var midVec = cornerIllum.GetMidVector();
            var ptMid  = ptCalc2d + midVec;

            if (!contour.IsPointInsidePolygon(ptMid.Convert3d()))
            {
                // инвертировать область
                cornerIllum.Invert();
            }

            var eastAngle = values.GetInsAngleFromAcad(cornerIllum.AngleStartOnPlane);

            CorrectEastStartAngle(eastAngle);
            CorrectWestStartAngle(values.GetInsAngleFromAcad(cornerIllum.AngleEndOnPlane));
        }
Exemple #5
0
        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);
        }