public static Vector3 GetMovedPoint(Vector3 pPoint) { //for better visualization: //- move to array center be at 0,0,0 pPoint -= arrayCenter; //- move to 0 height, flip Y axis (to match OBJ view format) //changed pPoint -= new Vector3(0, 0, CProjectData.GetMinHeight()); //pPoint -= new Vector3(0, CProjectData.GetMinHeight(), 0); return(pPoint); }
//public static Vector3 ParseHeaderVector3(string pXstring, string pYstring, string pZstring) //{ // float x = float.Parse(pXstring); // float y = float.Parse(pYstring); // float z = float.Parse(pZstring); // return new Vector3(x, y, z); //} public static Tuple <EClass, Vector3> ParseLine(string pLine, bool pUseHeader) { string[] split = pLine.Split(null); if (split.Length < 4 || (split.Length > 0 && split[0].Contains("#"))) { CDebug.WriteLine(pLine + " not valid"); return(null); } double x = double.Parse(split[0]); double y = double.Parse(split[1]); double z = double.Parse(split[2]); int _class = int.Parse(split[3]); //we don't use prescribed coordinate parsing as it produces badly visualisable terrain (with offset etc) //it should not have any effect on data processing Vector3 headerOffset = pUseHeader ? CProjectData.GetOffset() : Vector3.Zero; float xFloat = (float)(x - headerOffset.X); float yFloat = (float)(y - headerOffset.Y); float zFloat = (float)(z - headerOffset.Z); //swap canceled ////swap Y-Z. Y = height in this project //float tmp = yFloat; //yFloat = zFloat; //zFloat = tmp; EClass eClass = (EClass)_class; //Array acceptedClasses = Enum.GetValues(typeof(EClass)); //if(IsAcceptedClass(eClass)) //{ // _class = (int)EClass.Other; //} //if (_class != (int)EClass.Undefined && _class != (int)EClass.Ground && _class != (int)EClass.Vege) //{ // _class = (int)EClass.Other; //} return(new Tuple <EClass, Vector3>(eClass, new Vector3(xFloat, yFloat, zFloat))); }
/// <summary> /// Sets position, scale and rotation of tree obj to match given pTargetTree /// </summary> private static void SetRefTreeObjTransform(ref CRefTree pRefTree, CTree pTargetTree, int pAngleOffset) { Vector3 arrayCenter = CProjectData.GetArrayCenter(); float minHeight = CProjectData.GetMinHeight(); //float treeHeight = pTargetTree.peak.maxHeight.Y - (float)groundHeight; float treeHeight = pTargetTree.GetTreeHeight(); float heightRatio = treeHeight / pRefTree.GetTreeHeight(); pRefTree.Obj.Scale = heightRatio * Vector3.One; //align position to tree pRefTree.Obj.Position = pTargetTree.peak.Center; pRefTree.Obj.Position.Z -= pRefTree.GetTreeHeight() * heightRatio; //move obj so it is at 0,0,0 pRefTree.Obj.Position -= arrayCenter; pRefTree.Obj.Position -= Vector3.UnitZ * minHeight; pRefTree.Obj.Rotation = new Vector3(0, -pAngleOffset, 0); //in OBJ format Y = height CUtils.SwapYZ(ref pRefTree.Obj.Position); }
//class, position, note public static Tuple <int, Vector3, string> ParseLine(string pLine, bool pUseHeader) { string[] split = pLine.Split(null); //line example: //ID X Y Z POZN TYP CISLO_ //556 756123.256 5489291.262 923.47 *STROM403 11 403 //1 756168.829 5489339.169 936.49 rozhrani_plotu 52 if (!double.TryParse(split[1], out double x)) { return(null); } if (!double.TryParse(split[2], out double y)) { return(null); } if (!double.TryParse(split[3], out double z)) { return(null); } string _note = split[4]; if (string.IsNullOrEmpty(_note)) { return(null); } if (!int.TryParse(split[5], out int _class)) { return(null); } if (x > maxInputX) { maxInputX = x; } if (y > maxInputX) { maxInputY = y; } if (x < minInputX) { minInputX = x; } if (y < minInputY) { minInputY = y; } //we don't use prescribed coordinate parsing as it produces badly visualisable terrain (with offset etc) //it should not have any effect on data processing Vector3 headerOffset = pUseHeader ? CProjectData.GetOffset() : Vector3.Zero; float xFloat = (float)(x - headerOffset.X); float yFloat = (float)(y - headerOffset.Y); float zFloat = (float)(z - headerOffset.Z); //swap Y-Z. Y = height in this project float tmp = yFloat; yFloat = zFloat; zFloat = tmp; return(new Tuple <int, Vector3, string>(_class, new Vector3(xFloat, yFloat, zFloat), _note)); }
public static EProcessResult Start() { CSequenceController.SetValues(); DateTime startTime = DateTime.Now; CProjectData.Init(); CTreeManager.Init(); CAnalytics.Init(); CDartTxt.Init(); CLasExporter.Init(); CBiomassController.Init( CParameterSetter.GetStringSettings(ESettings.dbh), CParameterSetter.GetStringSettings(ESettings.agb)); CTreeRadiusCalculator.Init(); CShpController.Init(); CReftreeManager.Init(); Thread.CurrentThread.CurrentCulture = new CultureInfo("en"); //GENERAL CProjectData.useMaterial = true; CObjExporter.simplePointsObj = false; CMaterialManager.Init(); string[] workerResult = new string[2]; workerResult[0] = "this string"; workerResult[1] = "some other string"; CProjectData.backgroundWorker.ReportProgress(10, workerResult); try { List <string> tiledFiles = CProgramLoader.GetTiledPreprocessedFilePaths(); tilesCount = tiledFiles.Count; int startTile = CParameterSetter.GetIntSettings(ESettings.startIndex); if (startTile < 0 || startTile >= tiledFiles.Count) { throw new Exception($"Parameter startTile = {startTile}, tiledFiles.Count = {tiledFiles.Count}"); } for (int i = startTile; i < tiledFiles.Count; i++) { string tiledFilePath = tiledFiles[i]; EProcessResult tileProcess = ProcessTile(tiledFilePath, i); if (CProjectData.backgroundWorker.CancellationPending) { break; } } } catch (Exception e) { CDebug.Error( $"{Environment.NewLine}exception: {e.Message} {Environment.NewLine}{Environment.NewLine}" + $"StackTrace: {e.StackTrace}{Environment.NewLine}"); OnException(); return(EProcessResult.Exception); } if (CProjectData.backgroundWorker.CancellationPending) { CDebug.Step(EProgramStep.Cancelled); return(EProcessResult.Cancelled); } CDebug.Step(EProgramStep.ExportMainFiles); //TODO: implement this in super class for all controllers //dont create the main file if not needed if (tilesCount > 1) { CDartTxt.ExportMain(); CLasExporter.ExportMain(); CShpController.ExportMain(); } CBitmapExporter.ExportMain(); CDebug.Step(EProgramStep.Done); if (CSequenceController.IsLastSequence()) { CSequenceController.OnLastSequenceEnd(); return(EProcessResult.Done); } CSequenceController.currentConfigIndex++; return(Start()); }
private static EProcessResult ProcessTile(string pTilePath, int pTileIndex) { //has to reinit first for the correct progress output CDebug.ReInit(); DateTime startTime = DateTime.Now; currentTileIndex = pTileIndex; List <Tuple <EClass, Vector3> > parsedLines; if (CRxpParser.IsRxp) { CRxpInfo rxpInfo = CRxpParser.ParseFile(pTilePath); parsedLines = rxpInfo.ParsedLines; //for now we expect only one tile in rxp processing CProjectData.currentTileHeader = rxpInfo.Header; CProjectData.mainHeader = rxpInfo.Header; } else { string[] lines = CProgramLoader.GetFileLines(pTilePath); bool linesOk = lines != null && lines.Length > 0 && !string.IsNullOrEmpty(lines[0]); if (linesOk && CHeaderInfo.HasHeader(lines[0])) { //todo: where to init header? CProjectData.currentTileHeader = new CHeaderInfo(lines); } else { const string noHeaderMsg = "Processed tile has no header"; CDebug.Error(noHeaderMsg); throw new Exception(noHeaderMsg); } parsedLines = CProgramLoader.ParseLines(lines, true); } //has to be called after currentTileHeader is assigned CProjectData.ReInit(pTileIndex); //has to reinit after each tile is processed CTreeManager.Reinit(); if (CProjectData.backgroundWorker.CancellationPending) { return(EProcessResult.Cancelled); } CProgramLoader.ProcessParsedLines(parsedLines); if (CProjectData.backgroundWorker.CancellationPending) { return(EProcessResult.Cancelled); } CTreeManager.DebugTrees(); CDebug.Step(EProgramStep.Export3D); CObjPartition.ExportPartition("", "tile" + pTileIndex); if (CProjectData.backgroundWorker.CancellationPending) { return(EProcessResult.Cancelled); } //has to be called after ExportPartition where final folder location is determined try { CDebug.Step(EProgramStep.Bitmap); CBitmapExporter.Export(pTileIndex); } catch (Exception e) { CDebug.Error("exception: " + e.Message); } CAnalytics.totalDuration = CAnalytics.GetDuration(startTime); CDebug.Duration("total time", startTime); CDebug.Step(EProgramStep.Dart); CDartTxt.ExportTile(); CDebug.Step(EProgramStep.Shp); CShpController.ExportCurrent(); CDebug.Step(EProgramStep.Las); CLasExporter.ExportTile(); CDebug.Step(EProgramStep.Analytics); CAnalytics.Write(true); return(EProcessResult.Done); }
public static Obj ExportToObj(string pArrayName, EExportStrategy pStrategy, bool pUseSmoothHeight, Tuple <int, int> pStartIndex, Tuple <int, int> pEndIndex) { CGroundArray pArray = CProjectData.Points.groundArray; Obj obj = new Obj(pArrayName); float minHeight = CProjectData.GetMinHeight(); int missingCoordCount = 0; int xStart = pStartIndex.Item1; int yStart = pStartIndex.Item2; int xEnd = pEndIndex.Item1 + 1; int yEnd = pEndIndex.Item2 + 1; xEnd = Math.Min(xEnd, pArray.arrayXRange); yEnd = Math.Min(yEnd, pArray.arrayYRange); //prepare vertices for (int x = xStart; x < xEnd; x++) { for (int y = yStart; y < yEnd; y++) { Vertex v = new Vertex(); CGroundField el = pArray.GetField(x, y); float? height = el.GetHeight(pUseSmoothHeight ? CField.EHeight.Smooth : CField.EHeight.MaxZ); height = GetHeight(pStrategy, y, el, height); //create vertex only if height is defined if (height != null) { //TODO: ATTENTION! in OBJ the height value = Y, while in LAS format it is Z and X,Y are space coordinates //move heights so the lowest point touches the 0 //if (pHeight != EHeight.Tree) { height -= minHeight; } v.LoadFromStringArray(new[] { "v", pArray.GetFieldXCoord(x).ToString(), height.ToString(), pArray.GetFieldYCoord(y).ToString() }); obj.AddVertex(v); //record the index of vertex associated with this field position el.VertexIndex = obj.VertexList.Count; //first index = 1 (not 0)! } else { missingCoordCount++; } } } int faceCount = 0; //generate faces for (int x = xStart; x < xEnd - 1; x++) { for (int y = yStart; y < yEnd - 1; y++) { //create face only if all necessary vertices has been defined. -1 = not defined //| /| 3:[0,1] 2:[1,1] //|/ | 1:[0,0] 4:[1,0] //we create 2 faces: (1,2,3) and (1,2,4) int ind1 = pArray.GetField(x, y).VertexIndex; if (ind1 != -1) { int ind2 = pArray.GetField(x + 1, y + 1).VertexIndex; if (ind2 != -1) { int ind3 = pArray.GetField(x, y + 1).VertexIndex; if (ind3 != -1) { Face f = new Face(); f.LoadFromStringArray(new[] { "f", ind1.ToString(), ind2.ToString(), ind3.ToString() //ind1+"//"+ind3, ind3+"//"+ind2, ind2+"//"+ind1 }); obj.FaceList.Add(f); faceCount++; } int ind4 = pArray.GetField(x + 1, y).VertexIndex; if (ind4 != -1) { Face f = new Face(); f.LoadFromStringArray(new[] { "f", ind1.ToString(), ind4.ToString(), ind2.ToString() }); obj.FaceList.Add(f); } } } } } return(obj); }