/// <summary> /// Loads XYZ and SvBR profile from file at SV position. /// Multiple reloads of SvBR data might be possible to adjust off indexing based on malformed data. /// </summary> /// <param name="handle">File handles for XYZ and SvBR data.</param> /// <param name="sv">Sv position to load data at.</param> /// <param name="svRange">SvRange of patch (needed to calculate index).</param> /// <returns>XYZ/SvBR profile</returns> private Pair <IEnumerable <V3d> > LookUpProfile(Pair <PatchFileHandle> handle, double sv, Range1d svRange) { // sv to array index var index = handle.E0.PatchTree.Info.QuadVertexSortOrder == PatchFileInfo.QuadVertexSortOrderType.RowMajor ? SvToArrayIndex(sv, svRange, handle.E0.FileLoader.NumOfRows) : SvToArrayIndex(sv, svRange, handle.E0.FileLoader.NumOfColumns); // Load SvBR data. If indexing was not exact keep reloading neighboring profiles var pntsSvbr = new V3d[0]; var localSv = sv - handle.E1.PatchTree.Info.Local2Global2d.M03; int increment = 0; do { // Load data pntsSvbr = LookUpProfile(handle.E1, index); // For some reason we couldn't load any more data..... if (pntsSvbr == null || pntsSvbr.IsEmpty()) { break; } // NaN line, try next one if (pntsSvbr.Where(p => !p.IsNaN).IsEmptyOrNull()) { if (increment == 0) { break; } else { index += increment; continue; } } var avgSv = pntsSvbr.Where(p => !p.IsNaN).Average(p => p.X); // Profile close enough? if (avgSv.ApproximateEquals(localSv, AvgGeomtrySize / 2)) { break; } else { // nope, indexing must be off, try next one if (increment == 0) { increment = (avgSv < localSv) ? 1 : -1; } // if increment flips, than me might have a bigger hole between lines than AvgGeoSize else if (increment != ((avgSv < localSv) ? 1 : -1)) { break; } index += increment; } } while (!pntsSvbr.IsEmptyOrNull()); // Load XYZ data var pntsXyz = LookUpProfile(handle.E0, index); return(Pair.Create( pntsXyz.Select(pt => handle.E0.PatchTree.Info.Local2Global.TransformPos(pt)), pntsSvbr.Select(pt => handle.E0.PatchTree.Info.Local2Global2d.TransformPos(pt)) )); }