public void SaveObject(int navId, string key, ObjFormat format, string data) { using (var db = new AdminDbContext()) { var obj = db.Objs.FirstOrDefault(o => o.NavId == navId && o.Key.ToLower() == key.ToLower()); if (obj != null) { // update obj.Format = format; obj.Data = data; } else { // add db.Objs.Add(new Obj { NavId = navId, Key = key, Format = format, Data = data, }); } db.SaveChanges(); } }
public void TestParseFace3() { // given var expected = new ObjFormat.Face(); var obj = new ObjFormat(); expected.GeometricVertexReferences.AddRange(new List <int> { 1, 2, 3, 4 }); expected.NormalVertexReferences.AddRange(new List <int> { 1, 2, 3, 4 }); expected.TextureVertexReferences.AddRange(new List <int> { 1, 2, 3, 4 }); var completeLayout = "1/1/1 2/2/2 3/3/3 4/4/4"; // when var result = reader.ParseFace(completeLayout, obj); // then Assert.True(expected.GeometricVertexReferences.SequenceEqual(result.GeometricVertexReferences)); Assert.True(expected.NormalVertexReferences.SequenceEqual(result.NormalVertexReferences)); Assert.True(expected.TextureVertexReferences.SequenceEqual(result.TextureVertexReferences)); }
public void TestPerformEarClipping() { // given var vertices = new List <Vector4>() { new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), new Vector4(-0.5f, -0.5f, -0.5f, 1.0f), new Vector4(-0.5f, 0.5f, -0.5f, 1.0f), new Vector4(-0.5f, 0.5f, 0.5f, 1.0f), new Vector4(0.5f, -0.5f, 0.5f, 1.0f), new Vector4(0.5f, -0.5f, -0.5f, 1.0f), new Vector4(0.5f, 0.5f, -0.5f, 1.0f), new Vector4(0.5f, 0.5f, 0.5f, 1.0f), }; var vertexReferences = new List <int>() { 4, 3, 2, 1 }; var expected = new List <Mesh.Triangle>() { new Mesh.Triangle(new [] { new Vector3(-0.5f, 0.5f, 0.5f), new Vector3(-0.5f, 0.5f, -0.5f), new Vector3(-0.5f, -0.5f, -0.5f) }, new Vector3(-1f, 0f, 0f)), new Mesh.Triangle(new [] { new Vector3(-0.5f, 0.5f, 0.5f), new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(-0.5f, -0.5f, 0.5f) }, new Vector3(-1f, 0f, 0f)) }; // when var result = ObjFormat.PerformEarClipping(vertices, vertexReferences); // then Assert.AreEqual(expected.Count, result.Count); for (var i = 0; i < expected.Count; i++) { var t1 = expected[i]; var t2 = result[i]; for (var j = 0; j < 3; j++) { TestUtils.AssertVector3sAreEqualWithPrecision(t1.Vertices[j], t2.Vertices[j]); Assert.AreEqual(t1.Norm, t2.Norm); } } }
public Mesh ReadFromStream(Stream inputStream) { var obj = new ObjFormat(); using (var reader = new StreamReader(inputStream)) { while (reader.Peek() > -1) { var trimmedLine = reader.ReadLine()?.Trim(); if (string.IsNullOrEmpty(trimmedLine)) { continue; } var isComment = trimmedLine[0] == '#'; if (isComment) { continue; } var wordEnd = trimmedLine.IndexOf(' '); if (wordEnd > -1) { var firstWord = trimmedLine.Substring(0, wordEnd); var remainderLen = trimmedLine.Length - firstWord.Length; var remainder = trimmedLine.Substring(wordEnd, remainderLen).Trim(); switch (firstWord) { case "v": obj.GeometricVertices.Add(ParseGeometricVertex(remainder)); break; case "f": obj.Faces.Add(ParseFace(remainder, obj)); break; case "vt": obj.TextureVertices.Add(ParseTextureVertex(remainder)); break; case "vn": obj.VertexNormals.Add(ParseVertexNormal(remainder)); break; } } } } return(ObjFormat.ToMesh(obj)); }
public void TestCalculateTriangleNormal() { // given const float delta = 0.0001f; var expected = new Vector3(0.4422141f, -0.1679461f, -0.8810453f); var v1 = new Vector3(2.410367f, -0.777999f, -0.841105f); var v2 = new Vector3(2.407309f, -0.97498f, -0.805091f); var v3 = new Vector3(2.292449f, -0.871852f, -0.8824f); // when var result = ObjFormat.CalculateTriangleNormal(v1, v2, v3); // then TestUtils.AssertVector3sAreEqualWithPrecision(result, expected, delta); }
public void TestParseFace1() { // given var expected = new ObjFormat.Face(); var obj = new ObjFormat(); expected.GeometricVertexReferences.AddRange(new List <int> { 3, 4, 25, 26 }); var onlyVertexLayout = "3 4 25 26"; // when var result = reader.ParseFace(onlyVertexLayout, obj); // then Assert.True(expected.GeometricVertexReferences.SequenceEqual(result.GeometricVertexReferences)); }
internal ObjFormat.Face ParseFace(string str, ObjFormat obj) { var faceLayout = DetermineFaceLayout(str); var faceElementsPerLine = str.Split(' '); var result = new ObjFormat.Face(); foreach (var faceElement in faceElementsPerLine) { if (faceLayout != null && faceLayout.IsMatch(faceElement)) { if (faceLayout == OnlyVertices) { var vertexRef = ParseFaceElement(faceElement, obj.GeometricVertices.Count); result.GeometricVertexReferences.Add(vertexRef); } else if (faceLayout == Complete) { var elements = faceElement.Split('/'); result.GeometricVertexReferences.Add(ParseFaceElement(elements[0], obj.GeometricVertices.Count)); result.TextureVertexReferences.Add(ParseFaceElement(elements[1], obj.TextureVertices.Count)); result.NormalVertexReferences.Add(ParseFaceElement(elements[2], obj.VertexNormals.Count)); } else if (faceLayout == VerticesAndNormals) { var elements = faceElement.Split('/'); result.GeometricVertexReferences.Add(ParseFaceElement(elements[0], obj.GeometricVertices.Count)); result.NormalVertexReferences.Add(ParseFaceElement(elements[2], obj.VertexNormals.Count)); } else if (faceLayout == VerticesAndTexture) { var elements = faceElement.Split('/'); result.GeometricVertexReferences.Add(ParseFaceElement(elements[0], obj.GeometricVertices.Count)); result.TextureVertexReferences.Add(ParseFaceElement(elements[1], obj.TextureVertices.Count)); } } else { throw new FormatException($"Not recognizable .obj face element layout: {faceElement}"); } } return(result); }
public void TestParseFace2() { // given var expected = new ObjFormat.Face(); var obj = new ObjFormat(); expected.GeometricVertexReferences.AddRange(new List <int> { 1, 2, 3, 4 }); expected.NormalVertexReferences.AddRange(new List <int> { 1, 2, 3, 4 }); var vertexAndNormalLayout = "1//1 2//2 3//3 4//4"; // when var result = reader.ParseFace(vertexAndNormalLayout, obj); // then Assert.True(expected.GeometricVertexReferences.SequenceEqual(result.GeometricVertexReferences)); Assert.True(expected.NormalVertexReferences.SequenceEqual(result.NormalVertexReferences)); }
/// <summary> /// /// </summary> /// <param name="navId"></param> /// <param name="key"></param> /// <param name="format"></param> /// <param name="obj"></param> /// <remarks> /// SaveObject takes care of serialization, you just pass your object over. /// </remarks> public static void SaveObject(int navId, string key, ObjFormat format, object obj) { string str = ""; if (format == ObjFormat.Xml) str = Serializer.ConvertToString(obj); else if (format == ObjFormat.Html) str = (string)obj; Provider.SaveObject(navId, key, format, str); }
static void MainParallel(string[] args, MapProperties properties , string exportPath) { int max = 25; int current = 0; GaPSlabsVersion version = new GaPSlabsVersion("GaPSLabs 3D City Generator 1.0", 1, 0); if (!System.IO.Directory.Exists(exportPath)) System.IO.Directory.CreateDirectory(exportPath); Random rand = new Random((int)DateTime.Now.Ticks); MapProperties mapboundaries = new MapProperties(); if (properties != null) mapboundaries = properties; else { //mapboundaries.minLat = 59.3457; //mapboundaries.maxLat = 59.3527; //mapboundaries.minLon = 18.0609; //mapboundaries.maxLon = 18.0765; //mapboundaries.Name = "KTH Area"; mapboundaries.minLat = 59.2294; mapboundaries.maxLat = 59.4800; mapboundaries.minLon = 17.7649; mapboundaries.maxLon = 18.2977; mapboundaries.Name = "KTH Area"; mapboundaries.BuildingLineThickness = 0.6f; mapboundaries.RoadLineThickness = 0.2f; mapboundaries.Scale = new Vector2(16, 16); mapboundaries.BuildingColor = new Color(0, 255, 0); mapboundaries.LineColorStart = new Color(255, 255, 0); mapboundaries.LineColorEnd = new Color(255, 255, 0); mapboundaries.BuildingMaterial = null; mapboundaries.RoadMaterial = new Material("Route"); mapboundaries.CycleWayMaterial = new Material("RouteCycleway"); mapboundaries.FootWayMaterial = new Material("RouteFootway"); mapboundaries.RailWayMaterial = null; mapboundaries.StepsMaterial = new Material("RouteSteps"); mapboundaries.RoadWidth = 1;// 0.05f; mapboundaries.CyclewayWidth = 0.05f; mapboundaries.FootwayWidth = 0.05f; mapboundaries.BuildingHeight = 7.5f; mapboundaries.CombinationOptimizationSize = new Vector2(100, 100); } bool GenerateBuildingShapes = true; bool GenerateRoads = true; bool GenerateBuildings = true; bool CorrectAspectRatio = false; OSMPostgresqlSource source = new OSMPostgresqlSource(connPostGreSql); var bounds = source.Bounds; float[] minmaxX; float[] minmaxY; minmaxX = new float[] { 0, 5000 }; minmaxY = new float[] { 0, 5000 }; Bounds SelectedArea = new Bounds(); float LineWidth = 0.4f; float BuildingWidth = 0.6f; float height; height = 7.5f; SelectedArea.minlat = mapboundaries.minLat; SelectedArea.maxlat = mapboundaries.maxLat; SelectedArea.minlon = mapboundaries.minLon; SelectedArea.maxlon = mapboundaries.maxLon; minmaxX = mapboundaries.minMaxX; minmaxY = mapboundaries.minMaxY; if (CorrectAspectRatio) { var aspectRatio = System.Math.Abs(SelectedArea.maxlat - SelectedArea.minlat) / System.Math.Abs(SelectedArea.maxlon - SelectedArea.minlon); minmaxY[1] = (float)(minmaxX[1] * aspectRatio); } LineWidth = mapboundaries.RoadLineThickness; BuildingWidth = mapboundaries.BuildingLineThickness; height = mapboundaries.BuildingHeight; if (height < 4) height = 4; string[] ways = null; if (!GenerateRoads) { string[][] buildingtag = new string[1][]; buildingtag[0] = new string[] { "building", "" }; // NOTE: building tag in OSM is in lower case. ways = source.GetWayIdsWithTags(SelectedArea, buildingtag); } else if (!GenerateBuildings) { string[][] roadtag = new string[1][]; roadtag[0] = new string[] { "highway", "" }; // NOTE: highway tag in OSM is in lower case. ways = source.GetWayIdsWithTags(SelectedArea, roadtag); } else ways = source.GetWayIdsInBound(SelectedArea); float[] MinPointOnArea = CoordinateConvertor.SimpleInterpolation((float)SelectedArea.minlat, (float)SelectedArea.minlon, bounds, minmaxX, minmaxY); int direction = -1; Vector3 MinPointOnMap = new Vector3(direction * MinPointOnArea[0], 0, MinPointOnArea[1]); mapboundaries.MinPointOnMap = MinPointOnMap; int totalWays = ways.Length; int progress = 0; //List<OsmNode> WayNodes; //List<Tag> WayTags; //Vector3[] tempPoints; //PolygonCuttingEar.CPolygonShape shp; Console.WriteLine("Started at " + DateTime.Now + " for " + ways.Length + " objects."); var duration = Stopwatch.StartNew(); Parallel.ForEach<string>(ways, (FirstWay, state) => //foreach (var FirstWay in ways) { var w = new Way(FirstWay); List<OsmNode> WayNodes; List<Tag> WayTags; using (Npgsql.NpgsqlConnection con = new Npgsql.NpgsqlConnection(connPostGreSql)) { con.Open(); WayNodes = w.GetNodesPostgreSQL(FirstWay, con); WayTags = w.GetTagsPostgreSQL(FirstWay, con); con.Close(); } if (WayTags.Where(i => i.KeyValueSQL[0].ToLower() == "landuse" || i.KeyValueSQL[0].ToLower() == "building" || i.KeyValueSQL[0].ToLower() == "highway").Count() != 0) { var tempPoints = new Vector3[WayNodes.Count]; int counter = 0; foreach (var node in WayNodes) { var result = CoordinateConvertor.SimpleInterpolation((float)node.PositionSQL.Lat, (float)node.PositionSQL.Lon, bounds, minmaxX, minmaxY); // Testing the correct direction tempPoints[counter] = new Vector3(direction * (float)result[0], 0, (float)result[1]) - MinPointOnMap; counter++; } WayNodes = null; var building = WayTags.Where(i => i.KeyValueSQL[0].ToLower() == "building"); var highwayType = WayTags.Where(i => i.KeyValueSQL[0].ToLower() == "highway"); WayTags = null; if (building.Count() != 0) { if (GenerateBuildings) { //Debug.Log("Current building: "+FirstWay); if (GenerateBuildingShapes) { // Check if it has overlapping start and ending points. // NOTE: Replaced with the code to remove all the duplicates, not only the endpoints. // Checking for duplicates: tempPoints = tempPoints.ToArray().RemoveDuplicates(); var Skip = false; if (tempPoints.Length <= 2) { // Buildings that are too small to show such as 76844368 // http://www.openstreetmap.org/browse/way/76844368 // "A weird building were found and ignored. FirstWay \nRelated url: http://www.openstreetmap.org/browse/way/{0}" Skip = true; // continue; } if (!Skip) { var p2d = tempPoints.ToCPoint2D(); // TODO bug in the cpolygon, probably duplicates var shp = new PolygonCuttingEar.CPolygonShape(p2d); shp.CutEar(); p2d = null; GC.Collect(); // TODO: var randHeight = CoordinateConvertor.linear((float)rand.NextDouble(), 0, 1, -3f, height); var randMaterial = (randHeight > height / 2f) ? "BuildingTall" : randHeight < height / 2f ? "Building2" : "Building"; var resultedGameObject = shp.GenerateShapeUVedWithWalls_Balanced( CoordinateConvertor.OSMType.Polygon, FirstWay, "Building", "Building", randMaterial, height + randHeight, height + 7, true); //Console.WriteLine("Generating building..id=" + FirstWay); // To file: // ObjFormat.MeshToFile(resultedGameObject,System.IO.Path.Combine( exportPath , resultedGameObject.Name.Replace("|", "-") + ".obj")); // To PostGreSql LargeObjects: var objData = ObjFormat.GameObjectToString(resultedGameObject); var binaryData = System.Text.Encoding.ASCII.GetBytes(objData); AddToDatabase(binaryData, FirstWay, resultedGameObject.Name, resultedGameObject, version, connPostGreSql); // gc.id , gc is now set } } else Console.WriteLine("TODO"); // draw.Draw(tempPoints, buildingColor, buildingColor, BuildingWidth, BuildingWidth, LineDraw.OSMType.Line, FirstWay, "Building", "Building"); } } else { if (highwayType.Count() != 0) { if (GenerateRoads) { var hwtype = highwayType.First(); //Console.WriteLine("Generating roads..id=" + FirstWay); switch (hwtype.KeyValueSQL[1]) { case "cycleway": { var resultedGameObject = CoordinateConvertor.MeshGenerationFilledCorners(tempPoints.ToSegmentedPoints(2f), mapboundaries.CyclewayWidth, CoordinateConvertor.OSMType.Line, FirstWay, hwtype.KeyValueSQL[1], "Line", mapboundaries.CycleWayMaterial.Name, -0.01f); // ObjFormat.MeshToFile(resultedGameObject,System.IO.Path.Combine( exportPath , resultedGameObject.Name.Replace("|", "-") + ".obj")); // To PostGreSql LargeObjects: var objData = ObjFormat.GameObjectToString(resultedGameObject); var binaryData = System.Text.Encoding.ASCII.GetBytes(objData); AddToDatabase(binaryData, FirstWay, resultedGameObject.Name, resultedGameObject, version, connPostGreSql); // gc.id , gc is now set break; } case "footway": case "path": case "pedestrian": { var resultedGameObject = CoordinateConvertor.MeshGenerationFilledCorners(tempPoints.ToSegmentedPoints(4f), mapboundaries.FootwayWidth, CoordinateConvertor.OSMType.Line, FirstWay, hwtype.KeyValueSQL[1], "Line", mapboundaries.FootWayMaterial.Name, -0.01f); // ObjFormat.MeshToFile(resultedGameObject,System.IO.Path.Combine( exportPath , resultedGameObject.Name.Replace("|", "-") + ".obj")); // To PostGreSql LargeObjects: var objData = ObjFormat.GameObjectToString(resultedGameObject); var binaryData = System.Text.Encoding.ASCII.GetBytes(objData); AddToDatabase(binaryData, FirstWay, resultedGameObject.Name, resultedGameObject, version, connPostGreSql); // gc.id , gc is now set break; } case "steps": { var resultedGameObject = CoordinateConvertor.MeshGenerationFilledCorners(tempPoints.ToSegmentedPoints(4f), mapboundaries.CyclewayWidth, CoordinateConvertor.OSMType.Line, FirstWay, hwtype.KeyValueSQL[1], "Line", mapboundaries.StepsMaterial.Name, -0.01f); // ObjFormat.MeshToFile(resultedGameObject,System.IO.Path.Combine( exportPath , resultedGameObject.Name.Replace("|", "-") + ".obj")); // To PostGreSql LargeObjects: var objData = ObjFormat.GameObjectToString(resultedGameObject); var binaryData = System.Text.Encoding.ASCII.GetBytes(objData); AddToDatabase(binaryData, FirstWay, resultedGameObject.Name, resultedGameObject, version, connPostGreSql); // gc.id , gc is now set break; } case "motorway": { break; } default: { var resultedGameObject = CoordinateConvertor.MeshGenerationFilledCorners(tempPoints.ToSegmentedPoints(0.5f), mapboundaries.RoadWidth, CoordinateConvertor.OSMType.Line, FirstWay, hwtype.KeyValueSQL[1], "Line", mapboundaries.RoadMaterial.Name, 0f); // ObjFormat.MeshToFile(resultedGameObject,System.IO.Path.Combine( exportPath , resultedGameObject.Name.Replace("|", "-") + ".obj")); // To PostGreSql LargeObjects: var objData = ObjFormat.GameObjectToString(resultedGameObject); var binaryData = System.Text.Encoding.ASCII.GetBytes(objData); AddToDatabase(binaryData, FirstWay, resultedGameObject.Name, resultedGameObject, version, connPostGreSql); // gc.id , gc is now set break; } } //current++; //if (current > max) // state.Break(); } } } } }); duration.Stop(); Console.WriteLine("Finished in " + duration.Elapsed.Minutes + " minutes, " + duration.Elapsed.Seconds + " seconds, " + duration.Elapsed.Milliseconds + " milliseconds."); Console.ReadLine(); }