public void CanGetCentroid() { // ARRANGE var polygon = new List <Vector2d>() { new Vector2d(0, 0), new Vector2d(0, 10), new Vector2d(10, 10), new Vector2d(10, 0), }; // ACT var center = PolygonUtils.GetCentroid(polygon); // ASSERT Assert.AreEqual(new Vector2d(5, 5), center); }
public override List <MeshData> Build(Building building) { var roofOffset = building.Elevation + building.MinHeight + building.Height; var roofHeight = roofOffset + building.RoofHeight; // 1. detect the longest segment float length; Vector2d longestStart; Vector2d longestEnd; GetLongestSegment(building.Footprint, out length, out longestStart, out longestEnd); // 2. get direction vector var ridgeDirection = (new Vector3((float)longestEnd.X, roofOffset, (float)longestEnd.Y) - new Vector3((float)longestStart.X, roofOffset, (float)longestStart.Y)).normalized; // 3. get centroid var centroidPoint = PolygonUtils.GetCentroid(building.Footprint); var centroidVector = new Vector3((float)centroidPoint.X, roofHeight, (float)centroidPoint.Y); // 4. get something like center line Vector3 p1 = centroidVector + length * length * ridgeDirection; Vector3 p2 = centroidVector - length * length * ridgeDirection; // 5. detect segments which have intesection with center line Vector2d first, second; int firstIndex, secondIndex; DetectIntersectSegments(building.Footprint, new Vector2d(p1.x, p1.z), new Vector2d(p2.x, p2.z), out first, out firstIndex, out second, out secondIndex); if (firstIndex == -1 || secondIndex == -1) { Trace.Warn(LogCategory, Strings.RoofGenFailed, Name, building.Id.ToString()); return(base.Build(building)); } // prepare mesh and its index var mesh = CreateMesh(building.Footprint); var floorCount = building.Levels; var floorVertexCount = mesh.Triangles.Count * 3 * 2 * floorCount; var roofVertexCount = (building.Footprint.Count - 1) * 2 * 12; var vertexCount = roofVertexCount + floorVertexCount; var planeCount = building.Footprint.Count + floorCount; bool limitIsReached = false; if (vertexCount * 2 > Consts.MaxMeshSize) { vertexCount = roofVertexCount; planeCount = building.Footprint.Count; limitIsReached = true; } var meshIndex = new MultiPlaneMeshIndex(planeCount, vertexCount); var meshData = new MeshData(meshIndex, vertexCount); // 6. process all segments and create vertices FillMeshData(meshData, CustomizationService.GetGradient(building.RoofColor), roofOffset, roofHeight, building.Footprint, first, firstIndex, second, secondIndex); if (!limitIsReached) { AttachFloors(new RoofContext() { Mesh = mesh, MeshData = meshData, MeshIndex = meshIndex, Bottom = building.Elevation + building.MinHeight, FloorCount = floorCount, FloorHeight = building.Height / floorCount, FloorFrontGradient = CustomizationService.GetGradient(building.FloorFrontColor), FloorBackGradient = CustomizationService.GetGradient(building.FloorBackColor), IsLastRoof = false }); return(new List <MeshData>(1) { meshData }); } var meshDataList = BuildFloors(building, building.Levels, false); meshDataList.Add(meshData); return(meshDataList); }
/// <inheritdoc /> public override List <MeshData> Build(Building building) { var center = PolygonUtils.GetCentroid(building.Footprint); var roofOffset = building.Elevation + building.MinHeight + building.Height; var footprint = building.Footprint; var roofHeight = building.RoofHeight; var floorCount = building.Levels; var length = footprint.Count; var mesh = CreateMesh(footprint); var roofVertexCount = 12 * length; var floorVertexCount = mesh.Triangles.Count * 3 * 2 * floorCount; var vertexCount = roofVertexCount + floorVertexCount; var planeCount = building.Footprint.Count + floorCount; bool limitIsReached = false; if (vertexCount * 2 > Consts.MaxMeshSize) { vertexCount = roofVertexCount; planeCount = building.Footprint.Count; limitIsReached = true; } var meshIndex = new MultiPlaneMeshIndex(planeCount, vertexCount); var meshData = new MeshData(meshIndex, vertexCount); var roofGradient = CustomizationService.GetGradient(building.RoofColor); for (int i = 0; i < length; i++) { var nextIndex = i == (length - 1) ? 0 : i + 1; var v0 = new Vector3((float)footprint[i].X, roofOffset, (float)footprint[i].Y); var v1 = new Vector3((float)center.X, roofOffset + roofHeight, (float)center.Y); var v2 = new Vector3((float)footprint[nextIndex].X, roofOffset, (float)footprint[nextIndex].Y); var v01 = Vector3Utils.GetIntermediatePoint(v0, v1); var v12 = Vector3Utils.GetIntermediatePoint(v1, v2); var v02 = Vector3Utils.GetIntermediatePoint(v0, v2); meshIndex.AddPlane(v0, v1, v2, meshData.NextIndex); var color = GetColor(roofGradient, v0); meshData.AddTriangle(v0, v01, v02, color, color); color = GetColor(roofGradient, v01); meshData.AddTriangle(v02, v01, v12, color, color); color = GetColor(roofGradient, v02); meshData.AddTriangle(v2, v02, v12, color, color); color = GetColor(roofGradient, v01); meshData.AddTriangle(v01, v1, v12, color, color); } if (!limitIsReached) { AttachFloors(new RoofContext() { Mesh = mesh, MeshData = meshData, MeshIndex = meshIndex, Bottom = building.Elevation + building.MinHeight, FloorCount = floorCount, FloorHeight = building.Height / floorCount, FloorFrontGradient = CustomizationService.GetGradient(building.FloorFrontColor), FloorBackGradient = CustomizationService.GetGradient(building.FloorBackColor), IsLastRoof = false, }); return(new List <MeshData>(1) { meshData }); } var meshDataList = BuildFloors(building, building.Levels, false); meshDataList.Add(meshData); return(meshDataList); }