<commit_before>//
//  TGMapViewController.mm
//  TangramiOS
//
//  Created by <NAME> on 8/25/14.
//  Updated by <NAME> on 7/29/16.
//  Copyright (c) 2016 Mapzen. All rights reserved.
//

#import "TGMapViewController.h"
#import "Helpers.h"

#include "platform_ios.h"
#include "data/propertyItem.h"
#include "tangram.h"

__CG_STATIC_ASSERT(sizeof(TGMapMarkerId) == sizeof(Tangram::MarkerID));
__CG_STATIC_ASSERT(sizeof(TGGeoPoint) == sizeof(Tangram::LngLat));

@interface TGMapViewController ()

@property (nullable, copy, nonatomic) NSString* scenePath;
@property (nullable, strong, nonatomic) EAGLContext* context;
@property (assign, nonatomic) CGFloat pixelScale;
@property (assign, nonatomic) BOOL renderRequested;
@property (assign, nonatomic, nullable) Tangram::Map* map;

@end

@implementation TGMapViewController

#pragma mark Scene loading interface

- (void)loadSceneFile:(NSString*)path
{
    if (!self.map) { return; }

    self.scenePath = path;
    self.map->loadScene([path UTF8String]);
    self.renderRequested = YES;
}

- (void)loadSceneFileAsync:(NSString*)path
{
    if (!self.map) { return; }

    self.scenePath = path;

    MapReady onReadyCallback = [self, path](void* _userPtr) -> void {
        if (self.mapViewDelegate && [self.mapViewDelegate respondsToSelector:@selector(mapView:didLoadSceneAsync:)]) {
            [self.mapViewDelegate mapView:self didLoadSceneAsync:path];
        }

        self.renderRequested = YES;
    };

    self.map->loadSceneAsync([path UTF8String], false, onReadyCallback, nullptr);
}

#pragma mark Scene updates

- (void)queueSceneUpdate:(NSString*)componentPath withValue:(NSString*)value
{
    if (!self.map) { return; }

    self.map->queueSceneUpdate([componentPath UTF8String], [componentPath UTF8String]);
}

#pragma mark Longitude/Latitude - Screen position conversions

- (CGPoint)lngLatToScreenPosition:(TGGeoPoint)lngLat
{
    static const CGPoint nullCGPoint = {(CGFloat)NAN, (CGFloat)NAN};

    if (!self.map) { return nullCGPoint; }

    double screenPosition[2];
    if (self.map->lngLatToScreenPosition(lngLat.longitude, lngLat.latitude,
        &screenPosition[0], &screenPosition[1])) {
        return CGPointMake((CGFloat)screenPosition[0], (CGFloat)screenPosition[1]);
    }

    return nullCGPoint;
}

- (TGGeoPoint)screenPositionToLngLat:(CGPoint)screenPosition
{
    static const TGGeoPoint nullTangramGeoPoint = {NAN, NAN};

    if (!self.map) { return nullTangramGeoPoint; }

    screenPosition.x *= self.pixelScale;
    screenPosition.y *= self.pixelScale;

    TGGeoPoint lngLat;
    if (self.map->screenPositionToLngLat(screenPosition.x, screenPosition.y,
        &lngLat.longitude, &lngLat.latitude)) {
        return lngLat;
    }

    return nullTangramGeoPoint;
}

#pragma mark Feature picking

- (void)pickFeaturesAt:(CGPoint)screenPosition
{
    if (!self.map && !self.mapViewDelegate) { return; }

    screenPosition.x *= self.pixelScale;
    screenPosition.y *= self.pixelScale;

    self.map->pickFeaturesAt(screenPosition.x, screenPosition.y, [self](const auto& items) {
        NSMutableDictionary* dictionary = [[NSMutableDictionary alloc] init];
        CGPoint position = CGPointMake(0.0, 0.0);

        if (items.size() > 0) {
            const auto& result = items[0];
            const auto& properties = result.properties;
            position = CGPointMake(result.position[0], result.position[1]);

            for (const auto& item : properties->items()) {
                NSString* key = [NSString stringWithUTF8String:item.key.c_str()];
                NSString* value = [NSString stringWithUTF8String:properties->asString(item.value).c_str()];
                dictionary[key] = value;
            }
        }

        if ([self.mapViewDelegate respondsToSelector:@selector(mapView:didSelectFeatures:atScreenPosition:)]) {
            [self.mapViewDelegate mapView:self didSelectFeatures:dictionary atScreenPosition:position];
        }
    });
}

#pragma mark Marker implementation<commit_msg>Always return logical pixel position from interface<commit_after>//
//  TGMapViewController.mm
//  TangramiOS
//
//  Created by <NAME> on 8/25/14.
//  Updated by <NAME> on 7/29/16.
//  Copyright (c) 2016 Mapzen. All rights reserved.
//

#import "TGMapViewController.h"
#import "Helpers.h"

#include "platform_ios.h"
#include "data/propertyItem.h"
#include "tangram.h"

__CG_STATIC_ASSERT(sizeof(TGMapMarkerId) == sizeof(Tangram::MarkerID));
__CG_STATIC_ASSERT(sizeof(TGGeoPoint) == sizeof(Tangram::LngLat));

@interface TGMapViewController ()

@property (nullable, copy, nonatomic) NSString* scenePath;
@property (nullable, strong, nonatomic) EAGLContext* context;
@property (assign, nonatomic) CGFloat pixelScale;
@property (assign, nonatomic) BOOL renderRequested;
@property (assign, nonatomic, nullable) Tangram::Map* map;

@end

@implementation TGMapViewController

#pragma mark Scene loading interface

- (void)loadSceneFile:(NSString*)path
{
    if (!self.map) { return; }

    self.scenePath = path;
    self.map->loadScene([path UTF8String]);
    self.renderRequested = YES;
}

- (void)loadSceneFileAsync:(NSString*)path
{
    if (!self.map) { return; }

    self.scenePath = path;

    MapReady onReadyCallback = [self, path](void* _userPtr) -> void {
        if (self.mapViewDelegate && [self.mapViewDelegate respondsToSelector:@selector(mapView:didLoadSceneAsync:)]) {
            [self.mapViewDelegate mapView:self didLoadSceneAsync:path];
        }

        self.renderRequested = YES;
    };

    self.map->loadSceneAsync([path UTF8String], false, onReadyCallback, nullptr);
}

#pragma mark Scene updates

- (void)queueSceneUpdate:(NSString*)componentPath withValue:(NSString*)value
{
    if (!self.map) { return; }

    self.map->queueSceneUpdate([componentPath UTF8String], [componentPath UTF8String]);
}

#pragma mark Longitude/Latitude - Screen position conversions

- (CGPoint)lngLatToScreenPosition:(TGGeoPoint)lngLat
{
    static const CGPoint nullCGPoint = {(CGFloat)NAN, (CGFloat)NAN};

    if (!self.map) { return nullCGPoint; }

    double screenPosition[2];
    if (self.map->lngLatToScreenPosition(lngLat.longitude, lngLat.latitude,
        &screenPosition[0], &screenPosition[1])) {

        screenPosition[0] /= self.pixelScale;
        screenPosition[1] /= self.pixelScale;

        return CGPointMake((CGFloat)screenPosition[0], (CGFloat)screenPosition[1]);
    }

    return nullCGPoint;
}

- (TGGeoPoint)screenPositionToLngLat:(CGPoint)screenPosition
{
    static const TGGeoPoint nullTangramGeoPoint = {NAN, NAN};

    if (!self.map) { return nullTangramGeoPoint; }

    screenPosition.x *= self.pixelScale;
    screenPosition.y *= self.pixelScale;

    TGGeoPoint lngLat;
    if (self.map->screenPositionToLngLat(screenPosition.x, screenPosition.y,
        &lngLat.longitude, &lngLat.latitude)) {
        return lngLat;
    }

    return nullTangramGeoPoint;
}

#pragma mark Feature picking

- (void)pickFeaturesAt:(CGPoint)screenPosition
{
    if (!self.map && !self.mapViewDelegate) { return; }

    screenPosition.x *= self.pixelScale;
    screenPosition.y *= self.pixelScale;

    self.map->pickFeaturesAt(screenPosition.x, screenPosition.y, [screenPosition, self](const auto& items) {
        NSMutableDictionary* dictionary = [[NSMutableDictionary alloc] init];
        CGPoint position = CGPointMake(screenPosition.x / self.pixelScale, screenPosition.y / self.pixelScale);

        if (items.size() > 0) {
            const auto& result = items[0];
            const auto& properties = result.properties;
            position = CGPointMake(result.position[0] / self.pixelScale, result.position[1] / self.pixelScale);

            for (const auto& item : properties->items()) {
                NSString* key = [NSString stringWithUTF8String:item.key.c_str()];
                NSString* value = [NSString stringWithUTF8String:properties->asString(item.value).c_str()];
                dictionary[key] = value;
            }
        }

        if ([self.mapViewDelegate respondsToSelector:@selector(mapView:didSelectFeatures:atScreenPosition:)]) {
            [self.mapViewDelegate mapView:self didSelectFeatures:dictionary atScreenPosition:position];
        }
    });
}

#pragma mark Marker implementation
{'fraction_non_alphanumeric': 0.1257579432452098, 'fraction_numerical': 0.007761338830948338, 'mean_word_length': 3.897268408551069, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 27, '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': '7033813', 'n_tokens_mistral': 2708, 'n_tokens_neox': 2543, 'n_words': 500}