1 /**
2 Copyright: Copyright (c) 2016-2018 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 module voxelman.algorithm.arraycopy3d;
7 
8 import voxelman.math;
9 
10 /// writes source to a box within dest
11 void setSubArray3d(T)(
12 	T[] dest,
13 	ivec3 destSize,  // 7x8x9
14 	ivec3 destPos,
15 	T[] source,
16 	ivec3 sourceSize, // 4x5x6
17 	Box sourceBox, // (1,2,3) 2x3x4
18 	) @nogc
19 {
20 	assert(dest.length == destSize.x * destSize.y * destSize.z);
21 	assert(source.length == sourceSize.x * sourceSize.y * sourceSize.z);
22 
23 	const auto dest_size_y = destSize.x * destSize.z; // 1 y slice
24 	const auto source_size_y = sourceSize.x * sourceSize.z; // 1 y slice
25 
26 	foreach(y; 0..sourceBox.size.y)
27 	foreach(z; 0..sourceBox.size.z)
28 	{
29 		auto destY = y + destPos.y;
30 		auto destZ = z + destPos.z;
31 		auto fromDest = destY * dest_size_y + destZ * destSize.x + destPos.x;
32 		auto toDest = fromDest + sourceBox.size.x;
33 
34 		auto sourceY = y + sourceBox.position.y;
35 		auto sourceZ = z + sourceBox.position.z;
36 		auto fromSource = sourceY * source_size_y + sourceZ * sourceSize.x + sourceBox.position.x;
37 		auto toSource = fromSource + sourceBox.size.x;
38 
39 		dest[fromDest..toDest] = source[fromSource..toSource];
40 	}
41 }
42 
43 /// writes full source to a box within dest
44 void setSubArray3d(T)(T[] dest, ivec3 destSize, Box box, T[] source) @nogc
45 {
46 	const int dest_size_y = destSize.x * destSize.z; // 1 y slice
47 	assert(dest.length == dest_size_y * destSize.y);
48 	assert(source.length == box.volume);
49 
50 	if (box.position.x == 0 && box.size.x == destSize.x)
51 	{
52 		if (box.position.z == 0 && box.size.z == destSize.z)
53 		{
54 			if (box.position.y == 0 && box.size.y == destSize.y)
55 			{
56 				dest[] = source;
57 			}
58 			else
59 			{
60 				auto from = box.position.y * dest_size_y;
61 				auto to = (box.position.y + box.size.y) * dest_size_y;
62 				dest[from..to] = source;
63 			}
64 		}
65 		else
66 		{
67 			auto box_size_sqr = box.size.x * box.size.z;
68 			foreach(y; box.position.y..(box.position.y + box.size.y))
69 			{
70 				auto fromDest = y * dest_size_y + box.position.z * destSize.x;
71 				auto toDest = y * dest_size_y + (box.position.z + box.size.z) * destSize.x;
72 				auto sourceY = y - box.position.y;
73 				auto fromSource = sourceY * box_size_sqr + box.size.z;
74 				auto toSource = sourceY * box_size_sqr + box.position.z * box.size.z;
75 				dest[fromDest..toDest] = source[fromSource..toSource];
76 			}
77 		}
78 	}
79 	else
80 	{
81 		int posx = box.position.x;
82 		int endx = box.position.x + box.size.x;
83 		int endy = box.position.y + box.size.y;
84 		int endz = box.position.z + box.size.z;
85 		auto box_size_sqr = box.size.x * box.size.z;
86 
87 		foreach(y; box.position.y..endy)
88 		foreach(z; box.position.z..endz)
89 		{
90 			auto fromDest = y * dest_size_y + z * destSize.x + box.position.x;
91 			auto toDest = fromDest + box.size.x;
92 			auto sourceY = y - box.position.y;
93 			auto sourceZ = z - box.position.z;
94 			auto fromSource = sourceY * box_size_sqr + sourceZ * box.size.x;
95 			auto toSource = fromSource + box.size.x;
96 
97 			dest[fromDest..toDest] = source[fromSource..toSource];
98 		}
99 	}
100 }
101 
102 void setSubArray3d(T)(T[] dest, ivec3 destSize, Box box, T item) @nogc
103 {
104 	const int dest_size_y = destSize.x * destSize.z; // 1 y slice
105 	assert(dest.length == destSize.x * destSize.y * destSize.z);
106 
107 	if (box.position.x == 0 && box.size.x == destSize.x)
108 	{
109 		if (box.position.z == 0 && box.size.z == destSize.z)
110 		{
111 			if (box.position.y == 0 && box.size.y == destSize.y)
112 			{
113 				dest[] = item;
114 			}
115 			else
116 			{
117 				auto from = box.position.y * dest_size_y;
118 				auto to = (box.position.y + box.size.y) * dest_size_y;
119 				dest[from..to] = item;
120 			}
121 		}
122 		else
123 		{
124 			foreach(y; box.position.y..(box.position.y + box.size.y))
125 			{
126 				auto from = y * dest_size_y + box.position.z * destSize.x;
127 				auto to = y * dest_size_y + (box.position.z + box.size.z) * destSize.x;
128 				dest[from..to] = item;
129 			}
130 		}
131 	}
132 	else
133 	{
134 		int endy = box.position.y + box.size.y;
135 		int endz = box.position.z + box.size.z;
136 		foreach(y; box.position.y..endy)
137 		foreach(z; box.position.z..endz)
138 		{
139 			auto from = y * dest_size_y + z * destSize.x + box.position.x;
140 			auto to = from + box.size.x;
141 			dest[from..to] = item;
142 		}
143 	}
144 }