/// <summary> /// Initializes a new instance of the <see cref="VoxelizedSolid"/> class. /// </summary> /// <param name="ts">The ts.</param> /// <param name="voxelsOnLongSide">The voxels on long side.</param> /// <param name="bounds">The bounds.</param> public VoxelizedSolid(TessellatedSolid ts, int voxelsOnLongSide, IReadOnlyList <Vector3> bounds = null) : this() { if (bounds != null) { Bounds = new[] { bounds[0], bounds[1] } } ; else { Bounds = new[] { ts.Bounds[0], ts.Bounds[1] } }; Dimensions = Bounds[1].Subtract(Bounds[0]); SolidColor = new Color(ts.SolidColor.A, ts.SolidColor.R, ts.SolidColor.G, ts.SolidColor.B); VoxelSideLength = Math.Max(Dimensions.X, Math.Max(Dimensions.Y, Dimensions.Z)) / voxelsOnLongSide; numVoxelsX = (int)Math.Ceiling(Dimensions.X / VoxelSideLength); numVoxelsY = (int)Math.Ceiling(Dimensions.Y / VoxelSideLength); numVoxelsZ = (int)Math.Ceiling(Dimensions.Z / VoxelSideLength); voxels = new IVoxelRow[numVoxelsY * numVoxelsZ]; for (int i = 0; i < numVoxelsY * numVoxelsZ; i++) { voxels[i] = new VoxelRowSparse(numVoxelsX); } FillInFromTessellation(ts); FractionDense = 0; UpdateProperties(); }
/// <summary> /// Intersects the specified other rows with this row. /// </summary> /// <param name="others">The others.</param> /// <param name="offset">The offset.</param> public void Intersect(IVoxelRow[] others, int offset = 0) { for (int i = 0; i < others.Length; i++) { IVoxelRow other = others[i]; if (other is VoxelRowDense) { other = new VoxelRowSparse(other, other.maxNumberOfVoxels); } var otherIndices = ((VoxelRowSparse)other).indices; var otherLength = otherIndices.Count; var indexLowerBound = 0; if (otherLength == 0) { indices.Clear(); } else { if (otherIndices[0] != 0) { TurnOffRange(0, otherIndices[0], ref indexLowerBound); } for (int j = 1; j < otherLength - 1; j += 2) { TurnOffRange(otherIndices[j], otherIndices[j + 1], ref indexLowerBound); } TurnOffRange(otherIndices[otherLength - 1], other.maxNumberOfVoxels, ref indexLowerBound); } } }
/// <summary> /// Initializes a new instance of the <see cref="VoxelizedSolid"/> class. /// </summary> /// <param name="ts">The ts.</param> /// <param name="voxelSideLength">Length of the voxel side.</param> /// <param name="bounds">The bounds.</param> public VoxelizedSolid(TessellatedSolid ts, double voxelSideLength, IReadOnlyList <Vector3> bounds = null) : this() { if (bounds != null) { Bounds = new[] { bounds[0], bounds[1] } } ; else { Bounds = new[] { ts.Bounds[0], ts.Bounds[1] } }; Dimensions = Bounds[1].Subtract(Bounds[0]); SolidColor = new Color(Constants.DefaultColor); VoxelSideLength = voxelSideLength; numVoxelsX = (int)Math.Ceiling(Dimensions.X / VoxelSideLength); numVoxelsY = (int)Math.Ceiling(Dimensions.Y / VoxelSideLength); numVoxelsZ = (int)Math.Ceiling(Dimensions.Z / VoxelSideLength); voxels = new IVoxelRow[numVoxelsY * numVoxelsZ]; for (int i = 0; i < numVoxelsY * numVoxelsZ; i++) { voxels[i] = new VoxelRowSparse(); } FillInFromTessellation(ts); FractionDense = 0; UpdateProperties(); }
public static VoxelizedSolid CreateFullBlock(double voxelSideLength, IReadOnlyList <double[]> bounds) { var fullBlock = new VoxelizedSolid(); fullBlock.Bounds = new double[2][]; fullBlock.Bounds[0] = (double[])bounds[0].Clone(); fullBlock.Bounds[1] = (double[])bounds[1].Clone(); fullBlock.Dimensions = fullBlock.Bounds[1].subtract(fullBlock.Bounds[0]); fullBlock.SolidColor = new Color(Constants.DefaultColor); fullBlock.VoxelSideLength = voxelSideLength; var voxelsPerSide = fullBlock.Dimensions.Select(d => (int)Math.Ceiling(d / fullBlock.VoxelSideLength)).ToArray(); fullBlock.numVoxelsX = voxelsPerSide[0]; fullBlock.numVoxelsY = voxelsPerSide[1]; fullBlock.numVoxelsZ = voxelsPerSide[2]; fullBlock.voxels = new IVoxelRow[fullBlock.numVoxelsY * fullBlock.numVoxelsZ]; for (int i = 0; i < fullBlock.numVoxelsY * fullBlock.numVoxelsZ; i++) { var fullRow = new VoxelRowSparse(fullBlock.numVoxelsX); fullRow.indices.Add(0); fullRow.indices.Add((ushort)fullBlock.numVoxelsX); fullBlock.voxels[i] = fullRow; } fullBlock.UpdateProperties(); return(fullBlock); }
/// <summary> /// Initializes a new instance of the <see cref="VoxelizedSolid"/> class. /// </summary> /// <param name="ts">The ts.</param> /// <param name="voxelSideLength">Length of the voxel side.</param> /// <param name="bounds">The bounds.</param> public VoxelizedSolid(TessellatedSolid ts, double voxelSideLength, IReadOnlyList <double[]> bounds = null) : this() { Bounds = new double[2][]; if (bounds != null) { Bounds[0] = (double[])bounds[0].Clone(); Bounds[1] = (double[])bounds[1].Clone(); } else { Bounds[0] = (double[])ts.Bounds[0].Clone(); Bounds[1] = (double[])ts.Bounds[1].Clone(); } Dimensions = Bounds[1].subtract(Bounds[0]); SolidColor = new Color(Constants.DefaultColor); VoxelSideLength = voxelSideLength; var voxelsPerSide = Dimensions.Select(d => (int)Math.Ceiling(d / VoxelSideLength)).ToArray(); numVoxelsX = voxelsPerSide[0]; numVoxelsY = voxelsPerSide[1]; numVoxelsZ = voxelsPerSide[2]; voxels = new IVoxelRow[numVoxelsY * numVoxelsZ]; for (int i = 0; i < numVoxelsY * numVoxelsZ; i++) { voxels[i] = new VoxelRowSparse(); } FillInFromTessellation(ts); FractionDense = 0; UpdateProperties(); }
public void UpdateToAllSparse() { if (FractionDense == 0) { return; } for (int i = 0; i < numVoxelsY * numVoxelsZ; i++) { if (voxels[i] is VoxelRowSparse) { continue; } voxels[i] = new VoxelRowSparse((VoxelRowDense)voxels[i], numVoxelsX); } FractionDense = 0; }
/// <summary> /// Initializes a new instance of the <see cref="VoxelizedSolid"/> class. /// </summary> /// <param name="vs">The vs.</param> internal VoxelizedSolid(VoxelizedSolid vs) : this() { Bounds = new[] { vs.Bounds[0], vs.Bounds[1] }; Dimensions = Bounds[1].Subtract(Bounds[0]); SolidColor = new Color(vs.SolidColor.A, vs.SolidColor.R, vs.SolidColor.G, vs.SolidColor.B); VoxelSideLength = vs.VoxelSideLength; numVoxelsX = vs.numVoxelsX; numVoxelsY = vs.numVoxelsY; numVoxelsZ = vs.numVoxelsZ; voxels = new IVoxelRow[numVoxelsY * numVoxelsZ]; for (int i = 0; i < numVoxelsY * numVoxelsZ; i++) { voxels[i] = new VoxelRowSparse(vs.voxels[i], numVoxelsX); } FractionDense = 0; UpdateProperties(); }
/// <summary> /// Subtracts the specified subtrahend rows from this row. /// </summary> /// <param name="subtrahends">The subtrahends.</param> /// <param name="offset">The offset.</param> public void Subtract(IVoxelRow[] subtrahends, int offset = 0) { for (int i = 0; i < subtrahends.Length; i++) { IVoxelRow subtrahend = subtrahends[i]; if (subtrahend is VoxelRowDense) { subtrahend = new VoxelRowSparse(subtrahend, subtrahend.maxNumberOfVoxels); } var otherIndices = ((VoxelRowSparse)subtrahend).indices; var otherLength = otherIndices.Count; var indexLowerBound = 0; for (int j = 0; j < otherLength; j += 2) { TurnOffRange(otherIndices[j], otherIndices[j + 1], ref indexLowerBound); } } }
/// <summary> /// Unions the specified other rows with this row. /// </summary> /// <param name="others">The others.</param> /// <param name="offset">The offset.</param> public void Union(IVoxelRow[] others, int offset = 0) { for (int i = 0; i < others.Length; i++) { IVoxelRow other = others[i]; if (other is VoxelRowDense) { other = new VoxelRowSparse(other, other.maxNumberOfVoxels); } var otherIndices = ((VoxelRowSparse)other).indices; var otherLength = otherIndices.Count; var indexLowerBound = 0; for (int j = 0; j < otherLength; j += 2) { TurnOnRange(otherIndices[j], otherIndices[j + 1], ref indexLowerBound); } } }
public VoxelizedSolid(VoxelizedSolid vs) : this() { Bounds = new double[2][]; Bounds[0] = (double[])vs.Bounds[0].Clone(); Bounds[1] = (double[])vs.Bounds[1].Clone(); Dimensions = Bounds[1].subtract(Bounds[0]); SolidColor = new Color(vs.SolidColor.A, vs.SolidColor.R, vs.SolidColor.G, vs.SolidColor.B); VoxelSideLength = vs.VoxelSideLength; numVoxelsX = vs.numVoxelsX; numVoxelsY = vs.numVoxelsY; numVoxelsZ = vs.numVoxelsZ; voxels = new IVoxelRow[numVoxelsY * numVoxelsZ]; for (int i = 0; i < numVoxelsY * numVoxelsZ; i++) { voxels[i] = new VoxelRowSparse(vs.voxels[i], numVoxelsX); } FractionDense = 0; UpdateProperties(); }
/// <summary> /// Initializes a new instance of the <see cref="VoxelizedSolid"/> class. /// </summary> /// <param name="ts">The ts.</param> /// <param name="voxelsOnLongSide">The voxels on long side.</param> /// <param name="bounds">The bounds.</param> public VoxelizedSolid(IEnumerable <Polygon> loops, int voxelsOnLongSide, IReadOnlyList <Vector2> bounds) : this() { Bounds = new[] { new Vector3(bounds[0], 0), new Vector3(bounds[1], 1) }; Dimensions = Bounds[1].Subtract(Bounds[0]); VoxelSideLength = Math.Max(Dimensions.X, Math.Max(Dimensions.Y, Dimensions.Z)) / voxelsOnLongSide; numVoxelsX = (int)Math.Ceiling(Dimensions.X / VoxelSideLength); numVoxelsY = (int)Math.Ceiling(Dimensions.Y / VoxelSideLength); numVoxelsZ = 1; voxels = new IVoxelRow[numVoxelsY * numVoxelsZ]; for (int i = 0; i < numVoxelsY * numVoxelsZ; i++) { voxels[i] = new VoxelRowSparse(numVoxelsX); } var yBegin = Bounds[0][1] + VoxelSideLength / 2; var inverseVoxelSideLength = 1 / VoxelSideLength; // since its quicker to multiple then to divide, maybe doing this once at the top will save some time //if (loops.Any()) //{ // multiple enumeration warning so commenting out above condition. but that sound be a problem for next line var intersections = loops.AllPolygonIntersectionPointsAlongHorizontalLines(yBegin, numVoxelsY, VoxelSideLength, out var yStartIndex); var numYlines = intersections.Count; for (int j = -Math.Min(0, yStartIndex); j < numYlines; j++) { var intersectionPoints = intersections[j]; var numXRangesOnThisLine = intersectionPoints.Length; for (var m = 0; m < numXRangesOnThisLine; m += 2) { var sp = (ushort)((intersectionPoints[m] - Bounds[0][0]) * inverseVoxelSideLength); var ep = (ushort)((intersectionPoints[m + 1] - Bounds[0][0]) * inverseVoxelSideLength); if (ep >= numVoxelsX) { ep = (ushort)(numVoxelsX - 1); } ((VoxelRowSparse)voxels[yStartIndex + j]).indices.Add(sp); ((VoxelRowSparse)voxels[yStartIndex + j]).indices.Add(ep); } } //} FractionDense = 0; UpdateProperties(); }
/// <summary> /// Creates the full block given the dimensions and the size. /// </summary> /// <param name="voxelSideLength">Length of the voxel side.</param> /// <param name="bounds">The bounds.</param> /// <returns>VoxelizedSolid.</returns> public static VoxelizedSolid CreateFullBlock(double voxelSideLength, IReadOnlyList <Vector3> bounds) { var fullBlock = new VoxelizedSolid(); fullBlock.Bounds = new[] { bounds[0], bounds[1] }; fullBlock.Dimensions = fullBlock.Bounds[1].Subtract(fullBlock.Bounds[0]); fullBlock.SolidColor = new Color(Constants.DefaultColor); fullBlock.VoxelSideLength = voxelSideLength; fullBlock.numVoxelsX = (int)Math.Ceiling(fullBlock.Dimensions.X / fullBlock.VoxelSideLength); fullBlock.numVoxelsY = (int)Math.Ceiling(fullBlock.Dimensions.Y / fullBlock.VoxelSideLength); fullBlock.numVoxelsZ = (int)Math.Ceiling(fullBlock.Dimensions.Z / fullBlock.VoxelSideLength); fullBlock.voxels = new IVoxelRow[fullBlock.numVoxelsY * fullBlock.numVoxelsZ]; for (int i = 0; i < fullBlock.numVoxelsY * fullBlock.numVoxelsZ; i++) { var fullRow = new VoxelRowSparse(fullBlock.numVoxelsX); fullRow.indices.Add(0); fullRow.indices.Add((ushort)fullBlock.numVoxelsX); fullBlock.voxels[i] = fullRow; } fullBlock.UpdateProperties(); return(fullBlock); }