<commit_before>﻿using System.Collections.Generic;
using System.Linq;
using Mapsui.Geometries;
using Mapsui.Layers;
using Mapsui.Logging;
using Mapsui.Providers;
using Mapsui.Rendering;
using Mapsui.Styles;

namespace Mapsui.UI
{
    public static class InfoHelper
    {
        public static MouseInfoEventArgs GetInfoEventArgs(Map map, Point screenPosition, IEnumerable<ILayer> infoLayers,
            ISymbolCache symbolCache)
        {
            var worldPosition = map.Viewport.ScreenToWorld(new Point(screenPosition.X, screenPosition.Y));

            var feature = GetFeatureInfo(infoLayers, worldPosition, map.Viewport.Resolution, symbolCache);

            if (feature == null) return null;

            return new MouseInfoEventArgs { LayerName = "", Feature = feature };
        }

        private static IFeature GetFeatureInfo(IEnumerable<ILayer> layers, Point point, double resolution,
            ISymbolCache symbolCache)
        {
            foreach (var layer in layers)
            {
                if (layer.Enabled == false) continue;
                
                var allFeatures = layer.GetFeaturesInView(layer.Envelope, resolution);
                
                var features = allFeatures.Where(f => 
                    IsTouchingTakingIntoAccountSymbolStyles(point, f, layer.Style, resolution, symbolCache)).ToList();

                var feature = features.OrderBy(f => f.Geometry.GetBoundingBox().GetCentroid().Distance(point))
                    .FirstOrDefault();
                
                if (feature != null)
                {
                    return feature;
                }
            }
            return null;
        }

        private static bool IsTouchingTakingIntoAccountSymbolStyles(
            Point point, IFeature feature, IStyle layerStyle, double resolution, ISymbolCache symbolCache)
        {
            if (feature.Geometry is Point)
            {
                var styles = new List<IStyle>();
                if (layerStyle != null) styles.Add(layerStyle);
                styles.AddRange(feature.Styles);

                foreach (var style in styles)
                {
                    var symbolStyle = style as SymbolStyle;

                    if (symbolStyle == null)
                    {
                        Logger.Log(LogLevel.Warning, $"Feature info no supported for {style.GetType()}");
                        continue; //todo: add support for other types
                    }

                    var scale = symbolStyle.SymbolScale;

                    var size = symbolStyle.BitmapId >= 0
                        ? symbolCache.GetSize(symbolStyle.BitmapId)
                        : new Size(SymbolStyle.DefaultWidth, SymbolStyle.DefaultHeight);

                    var factor = resolution * scale;
                    var marginX = size.Width * 0.5 * factor;
                    var marginY = size.Height * 0.5 * factor;

                    var box = feature.Geometry.GetBoundingBox();
                    box = box.Grow(marginX, marginY);
                    box.Offset(symbolStyle.SymbolOffset.X * factor, symbolStyle.SymbolOffset.Y * factor);
                    if (box.Contains(point)) return true;
                }
            }
            return feature.Geometry.Contains(point);
        }
    }
}<commit_msg>Just comments<commit_after>﻿using System.Collections.Generic;
using System.Linq;
using Mapsui.Geometries;
using Mapsui.Layers;
using Mapsui.Logging;
using Mapsui.Providers;
using Mapsui.Rendering;
using Mapsui.Styles;

namespace Mapsui.UI
{
    public static class InfoHelper
    {
        public static MouseInfoEventArgs GetInfoEventArgs(Map map, Point screenPosition, IEnumerable<ILayer> infoLayers,
            ISymbolCache symbolCache)
        {
            var worldPosition = map.Viewport.ScreenToWorld(new Point(screenPosition.X, screenPosition.Y));

            var feature = GetFeatureInfo(infoLayers, worldPosition, map.Viewport.Resolution, symbolCache);

            if (feature == null) return null;

            return new MouseInfoEventArgs { LayerName = "", Feature = feature };
        }

        private static IFeature GetFeatureInfo(IEnumerable<ILayer> layers, Point point, double resolution,
            ISymbolCache symbolCache)
        {
            foreach (var layer in layers)
            {
                if (layer.Enabled == false) continue;
                
                var allFeatures = layer.GetFeaturesInView(layer.Envelope, resolution);
                
                var features = allFeatures.Where(f => 
                    IsTouchingTakingIntoAccountSymbolStyles(point, f, layer.Style, resolution, symbolCache)).ToList();

                var feature = features.OrderBy(f => f.Geometry.GetBoundingBox().GetCentroid().Distance(point))
                    .FirstOrDefault();
                
                if (feature != null)
                {
                    return feature;
                }
            }
            return null;
        }

        private static bool IsTouchingTakingIntoAccountSymbolStyles(
            Point point, IFeature feature, IStyle layerStyle, double resolution, ISymbolCache symbolCache)
        {
            if (feature.Geometry is Point)
            {
                var styles = new List<IStyle>();
                if (layerStyle != null) styles.Add(layerStyle);
                styles.AddRange(feature.Styles);

                foreach (var style in styles)
                {
                    var symbolStyle = style as SymbolStyle;

                    if (symbolStyle == null)
                    {
                        Logger.Log(LogLevel.Warning, $"Feature info not supported for {style.GetType()}");
                        continue; //todo: add support for other types
                    }

                    var scale = symbolStyle.SymbolScale;

                    var size = symbolStyle.BitmapId >= 0
                        ? symbolCache.GetSize(symbolStyle.BitmapId)
                        : new Size(SymbolStyle.DefaultWidth, SymbolStyle.DefaultHeight);

                    var factor = resolution * scale;
                    var marginX = size.Width * 0.5 * factor;
                    var marginY = size.Height * 0.5 * factor;

                    var box = feature.Geometry.GetBoundingBox();
                    box = box.Grow(marginX, marginY);
                    box.Offset(symbolStyle.SymbolOffset.X * factor, symbolStyle.SymbolOffset.Y * factor);
                    if (box.Contains(point)) return true;
                }
            }
            return feature.Geometry.Contains(point);
        }
    }
}
{'fraction_non_alphanumeric': 0.08089009171553149, 'fraction_numerical': 0.0015035333032626672, 'mean_word_length': 1.6375892149088025, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6401519', 'n_tokens_mistral': 1644, 'n_tokens_neox': 1536, 'n_words': 389}