How to Buffer a Point in NetTopologySuite v1.x

Below is a sample code to create a polygon in a circle form with specified center (WGS84 longitude, WGS84 latitude) and specified radius in meters.

using GeoAPI.Geometries;
using NetTopologySuite.Geometries;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;
namespace ConsoleApplication1
{
public static class GeometricOperations
{
/// <summary>
/// Createa a circle with the center:wgsLon,wgsLat and the given radius (in meters)
/// </summary>
/// <param name="wgsLat"></param>
/// <param name="wgsLon"></param>
/// <param name="radius">in meters</param>
public static IGeometry Buffer(double wgsLat, double wgsLon, double radius)
{
var coordinateSystemFactory = new CoordinateSystemFactory();
var coordinateTransformationFactory = new CoordinateTransformationFactory();
var WGS84CoordinateSystem = GeographicCoordinateSystem.WGS84;
var wkt3857 = "PROJCS[\"WGS 84 / World Mercator\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Mercator_1SP\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",0],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],AUTHORITY[\"EPSG\",\"3395\"]]";
var webMercatorCS = coordinateSystemFactory.CreateFromWkt(wkt3857);
var transformWGS84toWebMercator = coordinateTransformationFactory.CreateFromCoordinateSystems(WGS84CoordinateSystem, webMercatorCS);
var factoryWebMercator = new GeometryFactory(new PrecisionModel(PrecisionModel.MaximumPreciseValue), 3857);
var webMercatorIncidentCoordinate = transformWGS84toWebMercator.MathTransform.Transform(new double[] { wgsLon, wgsLat });
var webMercatorIncidentPoint = factoryWebMercator.CreatePoint(new Coordinate(webMercatorIncidentCoordinate[0], webMercatorIncidentCoordinate[1]));
int quadrantSegments = 12; // for maximum precision
return NetTopologySuite.Operation.Buffer.BufferOp.Buffer(webMercatorIncidentPoint, radius, quadrantSegments);
}
}
}

Transform WGS84 Point to Web Mercator in Net Topology Suite using Visual Studio Code

  • Open Visual Studio Code and in the command prompt navigate to the folder where you want to create your C# application. For example create a folder with the path “D:\work\NTS Test” and in VS Code command prompt type the following code and then press enter.
cd D:\work\NTS Test
  • In VS Code command prompt, run the following command to create a new C# Console Application in the current directory
dotnet new console
  • Install Net Topology Suite: In VS Code command prompt, run
dotnet add package NetTopologySuite --version 2.4.0
  • Install ProjNet: In VS Code command prompt, run
dotnet add package ProjNet --version 2.0.0
  • Replace the Program.cs content with the code block below
using ProjNet.CoordinateSystems.Transformations;
double wgs84Longitude = 32.889242;
double wgs84Latitude = 38.959570;
var result = CoordinateConverter.ConvertWGS84ToWebMercator(wgs84Longitude, wgs84Latitude);
Console.Write(result.X + " " + result.Y);
public class CoordinateConverter
{
public CoordinateConverter()
{
NetTopologySuite.NtsGeometryServices.Instance = new NetTopologySuite.NtsGeometryServices(
NetTopologySuite.Geometries.Implementation.CoordinateArraySequenceFactory.Instance,
new NetTopologySuite.Geometries.PrecisionModel(1000d),
4326,
NetTopologySuite.Geometries.GeometryOverlay.NG,
new NetTopologySuite.Geometries.CoordinateEqualityComparer());
}
public static NetTopologySuite.Geometries.Point ConvertWGS84ToWebMercator(double WGS84Longitude, double WGS84Latitude)
{
var gf = NetTopologySuite.NtsGeometryServices.Instance.CreateGeometryFactory(4326);
var WGS84Point = gf.CreatePoint(new NetTopologySuite.Geometries.Coordinate(WGS84Longitude, WGS84Latitude));
var sourceCoordSystem = ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84;
var targetCoordSystem = ProjNet.CoordinateSystems.ProjectedCoordinateSystem.WebMercator;
var WGS84toWebMercatorTransformation = new CoordinateTransformationFactory().CreateFromCoordinateSystems(sourceCoordSystem, targetCoordSystem);
var webMercatorPoint = Transform(WGS84Point, WGS84toWebMercatorTransformation.MathTransform);
return (NetTopologySuite.Geometries.Point)webMercatorPoint;
}
private static NetTopologySuite.Geometries.Geometry Transform(NetTopologySuite.Geometries.Geometry geom, MathTransform transform)
{
geom = geom.Copy();
geom.Apply(new MTF(transform));
return geom;
}
sealed class MTF : NetTopologySuite.Geometries.ICoordinateSequenceFilter
{
private readonly MathTransform _mathTransform;
public MTF(MathTransform mathTransform) => _mathTransform = mathTransform;
public bool Done => false;
public bool GeometryChanged => true;
public void Filter(NetTopologySuite.Geometries.CoordinateSequence seq, int i)
{
double x = seq.GetX(i);
double y = seq.GetY(i);
double z = seq.GetZ(i);
_mathTransform.Transform(ref x, ref y, ref z);
seq.SetX(i, x);
seq.SetY(i, y);
seq.SetZ(i, z);
}
}
}
view raw Program.cs hosted with ❤ by GitHub
  • Run the program with the following code and see the transformed point in the console.
dotnet run

References:

https://gis.stackexchange.com/a/294263


Transforming coordinates in a CSV file in Python

import csv
import os
from pyproj import Transformer

x,y=[],[]
inputFilePath='C:\\work\\coordinates4326.txt'
with open(inputFilePath) as f:
    reader=csv.reader(f,delimiter=' ')
    for row in reader:
        x.append(row[0])
        y.append(row[1])

outputFilePath='C:\\work\\coordinates3857.txt'
if os.path.exists(outputFilePath):
    os.remove(outputFilePath)

transformer = Transformer.from_crs("epsg:4326", "epsg:3857")
f2= open (outputFilePath,'a')
i=0
while i<len(x):
    x1,y1=x[i],y[i]
    lon,lat=transformer.transform(x1,y1)
    f2.write(str(lon)+' '+str(lat)+'\n')
    i=i+1
f2.close()
print('File successfully created at:'+outputFilePath)

Graphs

Graph is a data structure that contains nodes and the connection between nodes. We can represent this data in an adjacency matrix, adjacency list or as in our example below in adjacency dictionary where each node is a key, and adjacent nodes of the key node is the value.

Let’s examine the graph below:

There are 7 nodes in the graph and for example node-0 is connected to node-2 and node-1. The adjacency dictionary of this graph will be like this:

KeyValue
0[1,2]
1[0,3]
2[0,3,5]
3[1,2,4]
4[3]
5[2,6]
6[5]

Graphs can be traversed/searched in 2 ways:

Breadth-First Search (BFS)

In BFS, first source node is visited, then the neighbours of the source node are visited before moving to a deeper level in the graph. The algorithm of BFS can be as follows:

  • insert source node to visited items list
  • push all the adjacents of the source node to a queue
  • until queue has no items
    • eneque a node from queue (first added item in the queue)
    • if visited items list doesn’t contain node (will prevent infinite loop)
    • push the node to visited items list
    • add all the adjacents of the node to the queue

Depth-First Search (DFS)

DFS visits nodes as far as possible to the source node and then starts backtraking.

DFS algorithm can be as follows:

  • insert source node to visited items list
  • push all the adjacents of the source node to a stack
  • until stack has no items
    • pop a node from stack (last added item in the stack)
    • if visited items list doesn’t contain node (will prevent infinite loop)
    • push the node to visited items list
    • add all the adjacents of the node to the queue

Below is the C# code for BFS and DFS with recursive and iterative implementations.

 class Program
    {
        static void Main(string[] args)
        {
            var paths = new List<List<int>>();
            paths.Add(new List<int> { 0, 1 });
            paths.Add(new List<int> { 0, 2 });
            paths.Add(new List<int> { 1, 3 });
            paths.Add(new List<int> { 2, 3 });
            paths.Add(new List<int> { 2, 5 });
            paths.Add(new List<int> { 5, 6 });
            paths.Add(new List<int> { 3, 4 });

            var graph = CreateAdjacencyDictionary(paths);

            var visitedItems = BFS.Search(graph, 0);
            foreach (var item in visitedItems)
            {
                Console.WriteLine(item);
            }

            Console.ReadLine();

            return;
        }

        public static Dictionary<int, List<int>> CreateAdjacencyDictionary(List<List<int>> pairs)
        {
            Dictionary<int, List<int>> adjacencyDictionary = new Dictionary<int, List<int>>();

            foreach (var item in pairs)
            {
                if (!adjacencyDictionary.ContainsKey(item[0]))
                {
                    adjacencyDictionary.Add(item[0], new List<int>());
                }

                if (!adjacencyDictionary.ContainsKey(item[1]))
                {
                    adjacencyDictionary.Add(item[1], new List<int>());
                }

                adjacencyDictionary[item[0]].Add(item[1]);
                adjacencyDictionary[item[1]].Add(item[0]);
            }

            return adjacencyDictionary;
        }
    }
 public class BFS
    {
        public static List<int> Search(Dictionary<int, List<int>> graph,int key)
        {
            Queue<int> adjacents = new Queue<int>();
            List<int> visitedItems = new List<int>();
            BFSIterative(graph, visitedItems, adjacents,key);
            return visitedItems;
        }

        private static void BFSRecursive(Dictionary<int, List<int>> graph, List<int> visitedItems, Queue<int> adjacents, int key)
        {
            visitedItems.Add(key);
            foreach (var adj in graph[key])
            {
                adjacents.Enqueue(adj);
            }

            while (adjacents.Count > 0)
            {
                var toBeVisited = adjacents.Dequeue();

                if (!visitedItems.Contains(toBeVisited))
                {
                    BFSRecursive(graph, visitedItems, adjacents, toBeVisited);
                }
            }
        }

        private static void BFSIterative(Dictionary<int, List<int>> graph, List<int> visited, Queue<int> adjacents, int key)
        {
            visited.Add(key);
            foreach (var adj in graph[key])
            {
                adjacents.Enqueue(adj);
            }

            while (adjacents.Count > 0)
            {
                var toBeVisited = adjacents.Dequeue();

                if (!visited.Contains(toBeVisited))
                {
                    visited.Add(toBeVisited);
                    foreach (var adj in graph[toBeVisited])
                    {
                        adjacents.Enqueue(adj);
                    }
                }
            }
        }
    }
public class DFS
    {
        public static List<int> Search(Dictionary<int, List<int>> graph, int key)
        {
            Stack<int> adjacents = new Stack<int>();
            List<int> visited = new List<int>();
            DFSRecursive(graph, visited, adjacents, key);
            return visited;
        }

        private static void DFSRecursive(Dictionary<int, List<int>> graph, List<int> visited, Stack<int> adjacents, int key)
        {
            visited.Add(key);
            foreach (var adj in graph[key])
            {
                adjacents.Push(adj);
            }

            while (adjacents.Count > 0)
            {
                var toBeVisited = adjacents.Pop();

                if (!visited.Contains(toBeVisited))
                {
                    DFSRecursive(graph, visited, adjacents, toBeVisited);
                }
            }
        }

        private static void DFSIterative(Dictionary<int, List<int>> graph, List<int> visited, Stack<int> adjacents, int key)
        {
            visited.Add(key);
            foreach (var adj in graph[key])
            {
                adjacents.Push(adj);
            }

            while (adjacents.Count > 0)
            {
                var toBeVisited = adjacents.Pop();

                if (!visited.Contains(toBeVisited))
                {
                    visited.Add(toBeVisited);
                    foreach (var adj in graph[toBeVisited])
                    {
                        adjacents.Push(adj);
                    }
                }
            }
        }
    }

Türkçe Karakterleri İngilizce Karakterlere Çevirme-C#

Bir metindeki Türkçe karakterleri İngilizce karşılıklarına çevirmeye, SMS gönderme gibi pek çok durumda ihtiyaç duyabiliriz. Bunun için aşağıdaki kod bloğundaki ReplaceTurkishCharacters metodunu kullanabiliriz.

  static void Main(string[] args)
        {
            string turkishWord = "ÇçĞğİıÖöŞşÜü";
            var result = ReplaceTurkishCharacters(turkishWord);

            Console.WriteLine(string.Format("{0} --> {1}", turkishWord, result));
            Console.ReadLine();
        }

        public static string ReplaceTurkishCharacters(string turkishWord)
        {
            string source = "ığüşöçĞÜŞİÖÇ";
            string destination = "igusocGUSIOC";

            string result = turkishWord;

            for (int i = 0; i < source.Length; i++)
            {
                result = result.Replace(source[i], destination[i]);
            }

            return result;
        }

Professional Scrum Master-1 (PSM-1) Sınavı Hazırlık

Merhabalar,

Bu yazıdan PSM-I sertifika sınavını ve bu sınava nasıl sahip olabileceğinizden bahsedeceğim.
PSM-1 Scrum.org tarafından verilen bir Scrum Master sertifikasıdır. Bu sertifikaya sahip olmak için, Scrum.org üzerinden sunulan online sınavı en az 85 puanla tamamlamanız gerekiyor. Online sınav 80 sorudan oluşuyor ve 60 dakika süreniz bulunuyor.
Sınava 1 kez giriş ücreti 150 USD. Sınav tutarını ödedikten sonra, sınava istediğiniz bir tarihte girebiliyorsunuz.
https://www.scrum.org/professional-scrum-master-i-certification adresinde “BUY PSM I ASSESSMENT” butonuna basarak sınav giriş hakkı satın alabilirsiniz.

PSM-I sertifika sınavına hazırlanma aşamasında ise, kullanabileceğiniz kaynakları aşağıdan inceleyebilirsiniz.

1. Scrum Guide: PSM sınavını geçebilmeniz için, Scrum Guide ı birkaç kere okuyup her cümlesini iyice anladığınızdan emin olmalısınız. Scrum guide ı https://www.scrum.org/resources/scrum-guide adresinden indirebilirsiniz. Scrum Guide in Türkçe versiyonu da hazırlanmış, ona da göz atabilirsiniz ama sınav soruları da İngilizce olduğundan, tavsiyem İngilizce versiyonunu birkaç kere okumanız olacaktır.

2. Scrum Open Assessments: https://www.scrum.org/open-assessments/scrum-open Burada sınavda çıkabilecek örnek sorular bulunuyor. Buradaki testlerden 3 sefer üst üste 100 üzerinden 100 alana kadar testleri çözmeniz tavsiye ediliyor.

3. Online Scrum testleri: Aşağıda örnek soruların çözebileceğiniz birkaç site bulunuyor. Burada yer alan ya da benzeri sitelerden bol bol soru çözmenizi tavsiye ederim.

Scrum Guide ı okuyup iyice anlamak PSM-I sınavını geçebilmek için bilgi olarak yeterli. Testin yapısı ve soru kalıplarını anlamak için de Scrum Online Assessment lar ve başka web sitelerinde sunulan online testleri çözmek çok faydalı. Bu şekilde gerçek sınavda ciddi anlamda hız kazanıyorsunuz.
Ben yukarıdaki kaynaklara ek olarak Udemy den de online eğitim almıştım. Bu şekilde hazırlanarak 96 puanla PSM-I sınavını geçtim. Bana göre, sınavı geçebilmek için Udemy de eğitim almanız gerekmiyor. Hazırlanmak için önerim doğrudan Scrum Guide ı okuyup, olabildiğince soru çözmek olacak.

Sınava girecek herkese şimdiden başarılar diliyorum 🙂

Retrieve a Column Value from a Table Using Entity Framework

Entity Framework kullanılan bir projede, örnek olarak id si 11 olan bir öğrencinin yalnızca adı bilgisine ulaşmak istediğimizi varsayalım. Bu bilgiye ilgili DbSet üzerinden aşağıdaki şekilde kolaylıkla erişebiliriz.

var studentName= this.DbContext.Students.First(p=>p.Id==11).Name;

Bu şekilde sorgu çalıştırdığımızda, Visual Studio da output penceresini izlediğimizde, basit bir veri çekme işlemi için çok karmaşık sorgular oluşturulduğunu göreceğiz.

Bunun yerine, aşağıdaki şekilde bilgiyi getirmek daha basit sorgular oluşmasını ve sorgu süresinin çok daha kısa olmasını sağlayacaktır:

var studentName=
(from student in DbContext.Students
where student.Id=11
select student.Name).First() 

Eklenti Tabanlı Uygulama Geliştirme

Merhabalar, bu yazıda örnek bir uygulama üzerinden eklenti tabanlı mimariyi inceleyeceğiz. Eklenti tabanlı mimari temel olarak bir ana uygulama ve eklentilerden oluşur. Uygulamanın sahip olmasını istediğimiz yetenekler için eklentiler yazarız ve ana uygulama bu eklentileri dinamik olarak yükleyip çalıştırır. Ana uygulama ayağa kalktığında, belirtilmiş bir dizindeki eklentileri arar ve buradaki mevcut eklentileri çalışma zamanında yükler. Eklentiler çalışma zamanında yüklendiğinden uygulamaya yeni bir eklentinin eklenmesi ana uygulamada ve diğer eklentide herhangi bir kod güncellenmesine neden olmaz. Bu özellikleriyle, eklenti tabanlı uygulamalar oldukça esnek ve dinamik uygulamalardır.
Örnek uygulamamızda bir ana uygulama (“Host”), 2 eklenti (“String Analyzer” ve “Calculator”) ve ortak kullanılan veri yapılarının bulunacağı bir “Shared” projesi yer alacaktır. Örnek uygulamamız VS 2015, C# 4.0 ile bir desktop projesidir.
1. Shared
Ana uygulama ve pluginler tarafından ortak kullanılacak veri yapıları (genellikle interface ler) bu kütüphanede yer alır. Bizim örneğimizde bu kütüphanede yalnızca Iplugin interface i bulunmaktadır.
Bu interface te Name ve Description property leri ile GetUI() metodu yer almaktadır.
Sisteme yüklenecek plugin lerin bu interface i implement etmeleri gerekmektedir. Host uygulama da, kontrol edeceği dizinde bu interface i implement eden bir tipleri kontrol edecektir.
2. Host
Ana uygulamadır ve solutiondaki başlangıç (startup) projesidir. Kullanıcının göreceği ana ekran bu projede yer alır.
• Eklentilerin Yüklenmesi
Uygulamadaki önemli noktalardan birisi, solution daki plugin kütüphanelerinin bu projeye referans olarak eklenmemesidir. Bunun yerine önceden belirtilen dizindeki .dll uzantılı dosyalar kontrol edilir ve IPlugin interface ini implement eden bir tip varsa bu tipin bir instance ı oluşturulur. Bu instance lar bir plugin listesinde (List) tutulur ve ana ekranda yer alan menüden çağrıldığında ilgili eklenti çalıştırılır.

Aşağıda bu işlemlerin gerçekleştirildiği kod blogu bulunmaktadır. (Solution’da, Host projesinde PluginLoader sınıfında bulunur.)

   internal List LoadPlugins()
        {
            List plugins = new List();
            var pluginFilePath = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName + @"\Plugins\";

            string[] files = Directory.GetFiles(pluginFilePath, "*.dll");

            foreach (var file in files)
            {
                var assembly = Assembly.LoadFile(file);
                var calculationTypes = assembly.GetTypes().Where(t => typeof(IPlugin).IsAssignableFrom(t));
                foreach (var type in calculationTypes)
                {
                    var plugin = (IPlugin)Activator.CreateInstance(type);
                    plugins.Add(plugin);
                }
            }

            return plugins;
        }

• Ana Ekranın Gösterilmesi
Bizim örneğimizde, ana ekranda bir form ve form üzerinde bir toolstripbutton menü yer almaktadır.
Plugin listesindeki her plugin için toolstrip menüye bir buton eklenir, butonun adı pluginin adı, tooltip i pluginin description ıdır. Butona tıklandığında ise, pluginin GetUI() metodu çağrılır, bu şekilde pluginin kendi arayüzü gösterilir.
3. StringAnalyzer (Plugin-1)
Kullanıcı tarafından girilen bir metni, büyük harfe çeviren bir plugindir.
4. Calculator (Plugin-2)
Toplama işlemi yapan bir hesap makinesi pluginidir.

Uygulamamızın ekran görüntüsü aşağıdaki gibidir:

Main Form

Uygulamanın kaynak kodlarını ise buradan indirebilirsiniz.

Mutlu günler dilerim…

An exception of type ‘System.BadImageFormatException’ occurred in Project1.dll but was not handled in user code

An exception of type ‘System.BadImageFormatException’ occurred in Project1.dll but was not handled in user code

Additional information: Could not load file or assembly ‘Project2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’ or one of its dependencies. An attempt was made to load a program with an incorrect format.

I got this error and found out that, Platform target properties of Project1 and Project2 were different. Project1 was set to “Any CPU” and Project2 was set to “x64”. When I set “Any CPU” for Project2, the problem was fixed.
To check platform target property of a project,Right click Project in the solution explorer and choose Properties- Build and see “Platform Target” in the “General” section.