I coded the following simple GTK application. The target board that I use is TurboX-C610, that is manufactured by Thundercomm, and the firmware version is 200007.1.
#include <gtk/gtk.h>
int main(int argc, char *argv[]) {
GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_show(window);
g_signal_connect(window, "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
return 0;
}
I compiled the code by using cross compiler of Turbo-C610 that is provided by manufacturer. After doing that, I executed the program on target board by using ADB. But the following error is occurred. Because window system is Wayland, I do export GDK_DEGUG=wayland.
(mytest:5695): Gdk-WARNING **: 07:52:13.039: Error 22 (Invalid argument) dispatching to Wayland display.
When I did export WAYLAND_DEBUG=1, the logs are following,
[ 89809.336] -> wl_display#1.get_registry(new id wl_registry#2)
[ 89809.495] -> wl_display#1.sync(new id wl_callback#3)
[ 89809.832] wl_display#1.delete_id(3)
[ 89809.904] wl_registry#2.global(1, "wl_compositor", 3)
[ 89810.066] -> wl_registry#2.bind(1, "wl_compositor", 3, new id [unknown]#4)
[ 89810.190] wl_registry#2.global(2, "wl_subcompositor", 1)
[ 89810.278] -> wl_registry#2.bind(2, "wl_subcompositor", 1, new id [unknown]#5)
[ 89810.400] wl_registry#2.global(3, "wl_scaler", 2)
[ 89810.477] wl_registry#2.global(4, "presentation", 1)
[ 89810.560] wl_registry#2.global(5, "wl_pll", 1)
[ 89810.628] wl_registry#2.global(6, "wl_data_device_manager", 2)
[ 89810.713] -> wl_registry#2.bind(6, "wl_data_device_manager", 1, new id [unknown]#6)
[ 89810.827] wl_registry#2.global(7, "wl_shm", 1)
[ 89810.907] -> wl_registry#2.bind(7, "wl_shm", 1, new id [unknown]#7)
[ 89811.022] wl_registry#2.global(8, "wayland_buffer_backend", 4)
[ 89811.101] wl_registry#2.global(9, "wl_output", 3)
[ 89811.178] -> wl_registry#2.bind(9, "wl_output", 2, new id [unknown]#8)
[ 89811.303] -> wl_display#1.sync(new id wl_callback#9)
[ 89811.353] wl_registry#2.global(10, "zlinux_dmabuf", 1)
[ 89811.437] wl_registry#2.global(11, "gbm_buffer_backend", 1)
[ 89811.521] wl_registry#2.global(12, "wl_input_panel", 1)
[ 89811.605] wl_registry#2.global(13, "wl_text_input_manager", 1)
[ 89811.684] wl_registry#2.global(14, "wl_shell", 1)
[ 89811.768] wl_registry#2.global(15, "xdg_shell", 1)
[ 89811.843] -> wl_registry#2.bind(15, "xdg_shell", 1, new id [unknown]#10)
[ 89811.927] -> xdg_shell#10.use_unstable_version(5)
[ 89811.965] wl_registry#2.global(16, "desktop_shell", 3)
[ 89812.003] wl_registry#2.global(17, "workspace_manager", 1)
[ 89812.062] wl_registry#2.global(18, "screenshooter", 1)
[ 89812.147] wl_callback#3.done(0)
[ 89812.337] wl_display#1.delete_id(9)
[ 89812.362] wl_output#8.geometry(0, 0, 62, 110, 1, "unknown", "unknown", 0)
[ 89812.413] wl_output#8.scale(1)
[ 89812.422] wl_output#8.done()
[ 89812.432] wl_callback#9.done(0)
[ 89849.534] -> wl_shm#7.create_pool(new id wl_shm_pool#9, fd 6, 4096)
[ 89849.627] -> wl_shm_pool#9.resize(8832)
[ 89849.679] -> wl_shm_pool#9.resize(18624)
[ 89851.662] -> wl_compositor#4.create_surface(new id wl_surface#3)
[ 89851.704] -> wl_surface#3.set_opaque_region(nil)
[ 89851.720] -> wl_surface#3.set_input_region(nil)
[ 89852.011] -> wl_compositor#4.create_region(new id wl_region#11)
[ 89852.033] -> wl_surface#3.set_opaque_region(wl_region#11)
[ 89852.045] -> wl_region#11.destroy()
[ 89852.107] -> wl_compositor#4.create_region(new id wl_region#12)
[ 89852.120] -> wl_region#12.add(16, 13, 20, 20)
[ 89852.151] -> wl_surface#3.set_input_region(wl_region#12)
[ 89852.161] -> wl_region#12.destroy()
[ 89852.176] -> wl_compositor#4.create_region(new id wl_region#13)
[ 89852.185] -> wl_region#13.add(16, 13, 20, 20)
[ 89852.204] -> wl_surface#3.set_input_region(wl_region#13)
[ 89852.215] -> wl_region#13.destroy()
[ 89856.835] -> wl_surface#3.set_input_region(nil)
[ 89856.993] -> wl_surface#3.set_input_region(nil)
[ 89857.016] -> wl_surface#3.set_input_region(nil)
[ 89857.055] -> wl_surface#3.set_input_region(nil)
[ 89857.142] -> wl_surface#3.set_input_region(nil)
[ 89857.238] -> wl_surface#3.set_input_region(nil)
[ 89857.322] -> xdg_shell#10.get_xdg_surface(new id xdg_surface#14, wl_surface#3)
[ 89857.338] -> xdg_surface#14.set_parent(nil)
[ 89857.349] -> xdg_surface#14.set_title("mytest")
[ 89857.357] -> xdg_surface#14.set_window_geometry(26, 23, 59, 52)
[ 89857.380] -> xdg_surface#14.set_app_id("mytest")
[ 89868.738] -> wl_compositor#4.create_region(new id wl_region#15)
[ 89868.781] -> wl_region#15.add(33, 23, 45, 7)
[ 89868.795] -> wl_region#15.add(26, 30, 59, 45)
[ 89868.803] -> wl_surface#3.set_opaque_region(wl_region#15)
[ 89868.807] -> wl_region#15.destroy()
[ 89868.904] -> wl_compositor#4.create_region(new id wl_region#16)
[ 89868.920] -> wl_region#16.add(16, 13, 79, 72)
[ 89868.970] -> wl_surface#3.set_input_region(wl_region#16)
[ 89868.980] -> wl_region#16.destroy()
[ 89870.653] -> wl_compositor#4.create_region(new id wl_region#17)
[ 89870.684] -> wl_region#17.add(33, 23, 79, 7)
[ 89870.701] -> wl_region#17.add(26, 30, 93, 45)
[ 89870.719] -> wl_surface#3.set_opaque_region(wl_region#17)
[ 89870.728] -> wl_region#17.destroy()
[ 89870.777] -> wl_compositor#4.create_region(new id wl_region#18)
[ 89870.788] -> wl_region#18.add(16, 13, 113, 72)
[ 89870.808] -> wl_surface#3.set_input_region(wl_region#18)
[ 89870.818] -> wl_region#18.destroy()
[ 89870.951] -> wl_shm#7.create_pool(new id wl_shm_pool#19, fd 7, 60320)
[ 89870.980] -> wl_shm_pool#19.create_buffer(new id wl_buffer#20, 0, 145, 104, 580, 0)
[ 89872.995] -> wl_surface#3.attach(wl_buffer#20, 0, 0)
[ 89873.037] -> wl_surface#3.set_buffer_scale(1)
[ 89873.048] -> wl_surface#3.damage(0, 0, 145, 104)
[ 89873.083] -> wl_surface#3.frame(new id wl_callback#21)
[ 89873.095] -> wl_surface#3.commit()
[08:49:23.495] libwayland: file descriptor expected, object (7), message create_pool(nhi)
[ 89873.497] wl_display#1.delete_id(11)
[ 89873.524] wl_display#1.delete_id(12)
[ 89873.527] wl_display#1.delete_id(13)
[ 89873.543] wl_display#1.delete_id(15)
[ 89873.553] wl_display#1.delete_id(16)
[ 89873.563] wl_display#1.delete_id(17)
[ 89873.573] wl_display#1.delete_id(18)
[ 89873.583] wl_display#1.error(wl_display#1, 1, "invalid arguments for wl_shm#7.create_pool")
The error is related to wl_display_create_pool. So I researched on wl_shm and pool and relation of Wayland and GTK, but I can't get any solutions.
To solve this problem, I wonder what I should do.
Related
final Map<String, List<List<dynamic>>> originalData = {
"Chicago": [
[
8512,
7,
3620.15,
],
[
8421,
7,
5625,
],
],
"California": [
[
8512,
21,
11407.630000000001,
],
[
8708,
12,
5537.84,
],
]
};
Map<String, List<List<dynamic>>> myNewMap = Map.from(originalData);
myNewMap.forEach((st, data) {
data.forEach((List<dynamic> row) {
row.insert(0, st);
});
});
I tried Map.from(), ...OriginalData, and many more methods but it still change the OriginalData.
Expected Result should be:
myNewMap = {Chicago: [[Chicago, 8512, 7, 3620.15], [Chicago, 8421, 7, 5625]], California: [[California, 8512, 21, 11407.630000000001], [California, 8708, 12, 5537.84]]}
originalData = {Chicago: [[8512, 7, 3620.15], [8421, 7, 5625]], California: [[8512, 21, 11407.630000000001], [8708, 12, 5537.84]]}
Flutter uses shallow copy, but I also tried known methods of deep copy but nothing works.
Please help me to get over this.
I referred to this site. According to this site, the problem in your code is that in the multi-dimensional map the method used by you doesn't work it only works in one dimensional maps.
Full Code
import 'dart:convert';
void main() {
final Map originalData = {
"Chicago": [
[
8512,
7,
3620.15,
],
[
8421,
7,
5625,
],
],
"California": [
[
8512,
21,
11407.630000000001,
],
[
8708,
12,
5537.84,
],
]
};
Map myNewMap = json.decode(json.encode(originalData));
myNewMap.forEach((st, data) {
data.forEach((row) {
row.insert(0, st);
});
});
print("New Map: $myNewMap");
print("Original Map: $originalData");
}
Output
New Map: {Chicago: [[Chicago, 8512, 7, 3620.15], [Chicago, 8421, 7, 5625]], California: [[California, 8512, 21, 11407.630000000001], [California, 8708, 12, 5537.84]]}
Original Map: {Chicago: [[8512, 7, 3620.15], [8421, 7, 5625]], California: [[8512, 21, 11407.630000000001], [8708, 12, 5537.84]]}
Hope this helps. Happy Coding :)
How to access a Map element value by key, when a Map is inside a list?
'rooms': [
{
'roomNumber': 1,
'roomBeds': 1,
'roomColor': 1,
'roomNumOfDwellers': 0,
'roomDwellers': [
]
},
{
'roomNumber': 2,
'roomBeds': 3,
'roomColor': 2,
'roomNumOfDwellers': 0,
'roomDwellers': [
]
},
]
Tried this, doesn't work:
myPODO.rooms[1].['roomBeds']
The error message is:
Class '_InternalLinkedHashMap' has no instance getter 'roomBeds'.
Receiver: _LinkedHashMap len:5
Tried calling: roomBeds
Store the items in a list of Map and you can then print the values by key names.
void main() {
List<Map<String, dynamic>> rooms = [
{
'roomNumber': 1,
'roomBeds': 1,
'roomColor': 1,
'roomNumOfDwellers': 0,
'roomDwellers': [
]
},
{
'roomNumber': 2,
'roomBeds': 3,
'roomColor': 2,
'roomNumOfDwellers': 0,
'roomDwellers': [
]
},
];
print(rooms[1]['roomBeds']);
}
try to replace
myPODO.rooms[1].['roomBeds']
with
myPODO.rooms[1]['roomBeds']
I have following table data represented as scala's List[Map[String, Any]]
Following is scala code for creating such list of map
val inputData = List(
Map(
"d1_name" -> "t1",
"d1_id" -> 1,
"d2_name" -> "p1",
"d2_id" -> 11,
"value1" -> 5,
"value2" -> 12,
"value3" -> 30
),
Map(
"d1_name" -> "t1",
"d1_id" -> 1,
"d2_name" -> "p2",
"d2_id" -> 22,
"value1" -> 10,
"value2" -> 14,
"value3" -> 300
),
Map(
"d1_name" -> "t2",
"d1_id" -> 2,
"d2_name" -> "p3",
"d2_id" -> 33,
"value1" -> 15,
"value2" -> 16,
"value3" -> 33
),
Map(
"d1_name" -> "t3",
"d1_id" -> 3,
"d2_name" -> "p7",
"d2_id" -> 7,
"value1" -> 5,
"value2" -> 8,
"value3" -> 17
)
)
I want to convert shown input table to following pivoted output table in scala, the operation is to pivot "d1_name" column over value3 data, also dropping "d1_id" column in final output.
(i am expecting same List[Map[String, Any]] output type)
following is pictorial representation of output.
Try like this:
Use GroupBy with the column d1_name and for each element in the grouped list get modify data as required.
inputData.groupBy(_.getOrElse("d1_name", "")).flatMap(e => {
e._2.map(list => {
Map(
"d2_name" -> list.getOrElse("d2_name", ""),
"d2_id" -> list.getOrElse("d2_id", ""),
"value1" -> list.getOrElse("value1", 0),
"value2" -> list.getOrElse("value2", 0),
"value3" -> list.getOrElse("value3", 0),
if (e._1 == "t1") {"t1-value3" -> list.getOrElse("value3", 0)} else {"t1-value3" -> 0},
if (e._1 == "t2") {"t2-value3" -> list.getOrElse("value3", 0)} else {"t2-value3" -> 0},
if (e._1 == "t3") {"t3-value3" -> list.getOrElse("value3", 0)} else {"t3-value3" -> 0}
)
}
)
})
// List(
Map(value3 -> 30, t3-value3 -> 0, t2-value3 -> 0, d2_name -> p1, value1 -> 5, t1-value3 -> 30, value2 -> 12, d2_id -> 11),
Map(value3 -> 300, t3-value3 -> 0, t2-value3 -> 0, d2_name -> p2, value1 -> 10, t1-value3 -> 300, value2 -> 14, d2_id -> 22),
Map(value3 -> 17, t3-value3 -> 17, t2-value3 -> 0, d2_name -> p7, value1 -> 5, t1-value3 -> 0, value2 -> 8, d2_id -> 7),
Map(value3 -> 33, t3-value3 -> 0, t2-value3 -> 33, d2_name -> p3, value1 -> 15, t1-value3 -> 0, value2 -> 16, d2_id -> 33)
)
Hope this helps you.
---EDIT----
To generate the keys dynamically
val groupedInput = inputData.groupBy(_.getOrElse("d1_name", ""))
val uniqueKeys = groupedInput.keySet
groupedInput.flatMap(e => {
e._2.map(list => {
val value3= uniqueKeys.map(key => if (e._1 == key) {key+"-value3" -> list.getOrElse("value3", 0)} else {key+"-value3" -> 0})
Map(
List("d2_name" -> list.getOrElse("d2_name", ""),
"d2_id" -> list.getOrElse("d2_id", ""),
"value1" -> list.getOrElse("value1", 0),
"value2" -> list.getOrElse("value2", 0),
"value3" -> list.getOrElse("value3", 0)).++(value3) :_*
)
}
)
})
This version pivots "value3" based on the value of "d1_name", and deletes "d1_id". It leaves other values untouched. In a proper implementation these would be taken out as parameters, and there would be more error checking.
val defaults = // Compute default "table" for new pivot values
inputData
.map(_("d1_name").toString + "-" + "value3" -> 0)
.toMap
val pivot = // Add new pivot values to existing "table"
inputData.map { map =>
val d1Name = map("d1_name") + "-" + "value3"
map ++ defaults + (d1Name -> map("value3")) - "d1_name" - "d1_id"
}
I am working on N-Queens problem and to check whether the queen has been already placed on upper and lower left diagonals, I am finding difficulty in formulating for loop condition.
func isPlaceable(row: Int, column: Int) -> Bool {
// check if one same row another queen exits
for i in 0..<column {
if (solution[row][i] == 1) {
return false
}
}
// check upper left diagonal
// in C or C++ I can do
// for (int i = row, int j = col; i >= 0 && j >= 0; i--, j--) {
// if (board[i][j])
// return false;
//}
}
What would be Swifty way of doing it i.e. Combing the two condition?
One possible solution is you can use zip(_:_:) with two sequence.
func isPlaceable(row: Int, column: Int) -> Bool {
// check if one same row another queen exits
for i in 0..<column {
if (solution[row][i] == 1) {
return false
}
}
// check upper left diagonal
let seq1 = (0...row).reversed()
let seq2 = (0...column).reversed()
for (i,j) in zip(seq1, seq2) {
if (board[i][j]) {
return false
}
}
//your code
}
var i = row
var j = col
while (i >= 0 && j >= 0) {
if (board[i][j])
return false;
i -= 1
j -= 1
}
This type of process benefits a lot from double indirection and prepared matrices.
For example, you could give an identifier to each line segment on the board and check that no two queens use the same line segment.
There are 46 line segments on a standard chess board:
8 vertical
8 horizontal
30 diagonals (15 each)
(I numbered them 1 through 46)
When the queens are properly placed, they will each use 4 line segments (axes) that no other queen uses. Sets are the ideal structure to check for this non intersecting union. By preparing a matrix with a Set of 4 axis identifiers at each row/column, a simple union of the sets for the 8 queens will tell us if they align with each other.
// vertical axes (1...8)
let vAxis = [ [ 1, 2, 3, 4, 5, 6, 7, 8 ],
[ 1, 2, 3, 4, 5, 6, 7, 8 ],
[ 1, 2, 3, 4, 5, 6, 7, 8 ],
[ 1, 2, 3, 4, 5, 6, 7, 8 ],
[ 1, 2, 3, 4, 5, 6, 7, 8 ],
[ 1, 2, 3, 4, 5, 6, 7, 8 ],
[ 1, 2, 3, 4, 5, 6, 7, 8 ],
[ 1, 2, 3, 4, 5, 6, 7, 8 ]
]
// horizontal axes (9...16)
let hAxis = [ [ 9, 9, 9, 9, 9, 9, 9, 9 ],
[ 10, 10, 10, 10, 10, 10, 10, 10 ],
[ 11, 11, 11, 11, 11, 11, 11, 11 ],
[ 12, 12, 12, 12, 12, 12, 12, 12 ],
[ 13, 13, 13, 13, 13, 13, 13, 13 ],
[ 14, 14, 14, 14, 14, 14, 14, 14 ],
[ 15, 15, 15, 15, 15, 15, 15, 15 ],
[ 16, 16, 16, 16, 16, 16, 16, 16 ],
]
// up right axes (17...31)
let uAxis = [ [ 17, 18, 19, 20, 21, 22, 23, 24 ],
[ 18, 19, 20, 21, 22, 23, 24, 25 ],
[ 19, 20, 21, 22, 23, 24, 25, 26 ],
[ 20, 21, 22, 23, 24, 25, 26, 27 ],
[ 21, 22, 23, 24, 25, 26, 27, 28 ],
[ 22, 23, 24, 25, 26, 27, 28, 29 ],
[ 23, 24, 25, 26, 27, 28, 29, 30 ],
[ 24, 25, 26, 27, 28, 29, 30, 31 ],
]
// down right axes (32...46)
let dAxis = [ [ 39, 40, 41, 42, 43, 44, 45, 46 ],
[ 38, 39, 40, 41, 42, 43, 44, 45 ],
[ 37, 38, 39, 40, 41, 42, 43, 44 ],
[ 36, 37, 38, 39, 40, 41, 42, 43 ],
[ 35, 36, 37, 38, 39, 40, 41, 42 ],
[ 34, 35, 36, 37, 38, 39, 40, 41 ],
[ 33, 34, 35, 36, 37, 38, 39, 40 ],
[ 32, 33, 34, 35, 36, 37, 38, 39 ],
]
// Set of axis numbers for each [row][col] of the board
let axes = (0..<8).map()
{
row in (0..<8).map()
{ Set([ vAxis[row][$0], hAxis[row][$0], uAxis[row][$0], dAxis[row][$0] ]) }
}
// position of each queen ( column number at each row )
var queenCols = [5, 3, 6, 0, 7, 1, 4, 2]
// Check if each queen in queenCols is on its own 4 axes
// We will have 32 (8 x 4) different axes used if no queen aligns with another
let fullCover = queenCols.enumerated()
.reduce(Set<Int>()){ $0.union(axes[$1.0][$1.1]) }
.count == 32
This "fullCover" check can be used in a brute force loop on all 16,777,216 combinations or it can be refined to perform incremental checks in an optimized search tree. (BTW the brute force solution takes only 80 seconds to compute on a MacBook Pro)
So, in the end, you can avoid for loops altogether.
[EDIT] function to find the 92 solutions in a brute force loop:
public func queenPositions() -> [[Int]]
{
var result : [[Int]] = []
let rows : [Int] = Array(0..<8)
for i in 0..<16777216
{
var N:Int = i
let queenCols = rows.map{ _ -> Int in let col = N % 8; N = N / 8; return col}
let fullCover = queenCols.enumerated()
.reduce(Set<Int>()){ $0.union(axes[$1.0][$1.1]) }
.count == 32
if fullCover { result.append(queenCols) }
}
return result
}
[EDIT2] Using the set matrices in an optimized tree search produces the 92 solutions in 0.03 second.
Here is the optimized (and generic) function:
public func queenPositions2(boardSize:Int = 8) -> [[Int]]
{
let vAxis = (0..<boardSize).map{ _ in (0..<boardSize).map{$0} }
let hAxis = (0..<boardSize).map{ Array(repeating:$0+boardSize, count:boardSize) }
let uAxis = (0..<boardSize).map{ row in (0..<boardSize).map{ 2 * boardSize + row + $0} }
let dAxis = (0..<boardSize).map{ row in (0..<boardSize).map{ 5 * boardSize - row + $0} }
let axes = (0..<boardSize).map()
{
row in (0..<boardSize).map()
{ Set([ vAxis[row][$0], hAxis[row][$0], uAxis[row][$0], dAxis[row][$0] ]) }
}
var result : [[Int]] = []
var queenCols : [Int] = Array(repeating:0, count:boardSize)
var colAxes = Array(repeating:Set<Int>(), count:boardSize)
var queenAxes = Set<Int>()
var row = 0
while row >= 0
{
if queenCols[row] < boardSize
{
let newAxes = axes[row][queenCols[row]]
if newAxes.isDisjoint(with: queenAxes)
{
if row == boardSize - 1
{
result.append(queenCols)
queenCols[row] = boardSize
continue
}
else
{
colAxes[row] = newAxes
queenAxes.formUnion(newAxes)
row += 1
queenCols[row] = 0
continue
}
}
}
else
{
row -= 1
if row < 0 { break }
}
queenAxes.subtract(colAxes[row])
colAxes[row] = Set<Int>()
queenCols[row] += 1
}
return result
}
Given a 10x10 board, the 724 solutions are generated in 0.11 second.
[EDIT3] one liner "for loop" ...
You can generate an array of (row,column) coordinate for the 4 axes of a given position and use that as your data in the for loop:
func isPlaceable(row: Int, column: Int) -> Bool
{
var coverage = (0..<8).map{($0,column)} // horizontal
coverage += (0..<8).map{(row,$0)} // vertical
coverage += zip((max(0,row-column)..<8),(max(0,column-row)..<8)) // diagonal down
coverage += zip((0...min(7,row+column)).reversed(),(max(0,column+row-7)..<8)) // diagonal up
// return !coverage.contains{solution[$0][$1] == 1}
for (r,c) in coverage
{
if solution[r][c] == 1 { return false }
}
return true
}
It feels wasteful to rebuild the whole coverage list every time though. I would compute it once for every coordinate and place it in a row/column matrix for reuse in the isPlaceable() function.
i wish to chain cubes end to end inside a loop, so that i can construct a spiral made of cubes only using dynamic rules of how they are added together rather than a parametric equation. i.e. translate 1, tilt 20', rotate-z 10'... would make a 3d spirograph.
Here is an example file using openscad recursion (which memory-crashes very fast compared to openscad loops) i wish to do the same using a loop? i am confused.
levels = 50; // number of levels for the recursion
len = 100; // length of the first segment
thickness = 5; // thickness of the first segment
// the identity matrix
identity = [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ];
// random generator
function rnd(s, e) = rands(s, e, 1)[0];
// generate 4x4 translation matrix
function mt(x, y) = [ [ 1, 0, 0, x ], [ 0, 1, 0, y ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ];
// generate 4x4 rotation matrix around Z axis
function mr(a) = [ [ cos(a), -sin(a), 0, 0 ], [ sin(a), cos(a), 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ];
module tree(length, thickness, count, m = identity) {
color([0, 1 - (0.8 / levels * count), 0])
multmatrix(m)
cube([thickness, length, thickness]);
if (count > 0) {
tree( length, thickness, count - 1, m * mt(0, length) * mr(31.4159));
}
}
tree(len, thickness, levels);
We can generate the list of matrices in a recursive function first
and use the result in a for() module to generate the actual geometry.
// the identity matrix
identity = [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ];
// generate 4x4 rotation matrix around Z axis
function mr(a) = [ [ cos(a), -sin(a), 0, 0 ], [ sin(a), cos(a), 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ];
// generate 4x4 translation matrix
function mt(x, y) = [ [ 1, 0, 0, x ], [ 0, 1, 0, y ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ];
function matrices(i = 10, m = identity, ret = []) = i >= 0
? matrices(i - 1, m * mt(0, 10) * mr(20), concat(ret, [ m ]))
: ret;
for (m = matrices(17))
multmatrix(m)
cube([5, 10, 5]);
with help form Torsten Paul.