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