openscad drill into group created by for - openscad

I know that when I use for it creates a group of the generated children.
I created a module called grid like so:
module grid(x0,y0,dx,dy,nx,ny) {
for (x=[0:1:nx-1]) {
for(y=[0:1:ny-1]) {
i=x*nx+y;
echo(i);
translate([x0+x*dx,y0+y*dy,0]) children(i);
}
}
}
which when used like this:
grid(-50,-50,25,25,5,5) {
cube([10,10,10],center=true);
cube([10,10,10],center=true);
cube([10,10,10],center=true);
cube([10,10,10],center=true);
//.. continue to create 25 cubes total
}
arranges the cubes in a nice grid.
however my original hope and intention was to use it like this:
grid(-50,-50,25,25,5,5) {
for(i=[0:1:24]) {
cube([10,10,10],center=true);
}
}
Which fails because the for operator returns a group and not a set of children.
Why does the for add a group to begin with? (also leading to the need for intersection_for)
And is there a way for my Grid operator module to handle the children of the group?

I personally hope for the grouping/union for elements within a for() to become optional at some time.
If you don't mind compiling OpenSCAD from source, you could try it already today.
There is an ongoing issue Lazy union (aka. no implicit union)
and a patch here Make for() UNION optional

Just updated my knowledge of OpenSCAD, there is a better solution:
module nice_cube()
{
translate([0,0,$height/2]) cube([9,9,$height], center = true);
}
module nice_cylinder()
{
translate([0,0,$height/2]) cylinder(d=10,h=$height, center = true);
}
module nice_text()
{
linear_extrude(height=$height, center=false) text(str($height), size=5);
}
module nice_grid()
{
for(i=[0:9], j=[0:9])
{
$height=(i+1)*(j+1);
x=10*i;
y=10*j;
translate([x,y,0]) children();
/* let($height=(i+1)*(j+1)) {children();} */
}
}
nice_grid() nice_cube();
translate([0,-110,0]) nice_grid() nice_text();
translate([-110,0,0]) nice_grid() nice_cylinder();
The trick here is to control the shape produced by module by special variables (starting with $) those can be used like in example, commented line using let() requires development version of openscad.

I guess You want this:
for(x=[...], y=[...]) {
translate([x,y,0]) children();
}
Note, that you need only one for statement to loop through both x and y values.
What I have understood from your comment is, that you want your objects in the nodes of the grids to be parametric, and parameter depends on index. This requirement was not mentioned in the original question. In this case, solution depends on your problem context, I guess. The two possibilities I see are:
module grid_of_parametric_modules(other_param)
{
for(i=[0:24])
{
x=_x(i);
y=_y(i);
translate([x,y,0]) parametric_module(i_param(i), other_param);
}
}
However this may not be suitable, especially if You are going to add new shapes to your grid in future. Then you can probably do it like:
function grid_pos(i) = [_x(i), _y(i), 0];
....
for(i=[0:24])
translate(grid_pos(i)) parametric_module(i);

Related

ag-grid setModel equivalent of selectValue

Using ag-grid 23.2.1, it looks like our current approach to filtering is on it's way out and listed as deprecated. Reading over the setModel documentation, I don't readily see a way to replace some of our selectValue, selectNothing, etc. usage.
Example 1: we clear the selection and then pick a couple of values on some condition else we select all
let filterInstance = this.gridOptions.api.getFilterInstance('make');
this.cacheFilterModel = this.gridOptions.api.getFilterModel();
if (condition) {
filterInstance.selectNothing();
filterInstance.selectValue('thing1');
filterInstance.selectValue('thing2');
}
else {
filterInstance.selectEverything();
}
filterInstance.applyModel();
this.gridOptions.api.onFilterChanged();
Example 2: we have some filter values in a column toggle-able via checkboxes, which call a method like the below. if one of the values is checked it gets added to the existing filter, if unchecked the value is removed. There could be values already filtered and I don't really see a way to contextually select/unselect values using setModel.
filterExample (make, add) {
let filterInstance = this.gridOptions.api.getFilterInstance('make');
if (add) {
filterInstance.selectValue(make);
}
else {
filterInstance.unselectValue(make);
}
filterInstance.applyModel();
this.gridOptions.api.onFilterChanged();
}
Are there setModel equivalents for these?
I had a similar issue with setColumnFilter where I had to pass a few values. You can use filterInstance.setModel to set these values by passing an array like so:
filterInstance.setModel({ values: ['value1', 'value2'] })
filterInstance.applyModel();
gridOptions.api.onFilterChanged()
here is a link to how to do it from the docs. I found this hard to find on google so providing it here.
https://www.ag-grid.com/javascript-grid-filter-set-api/

How to write to an Element in a Set?

With arrays you can use a subscript to access Array Elements directly. You can read or write to them. With Sets I am not sure of a way to write its Elements.
For example, if I access a set element matching a condition I'm only able to read the element. It is passed by copy and I can't therefore write to the original.
For example:
columns.first(
where: {
$0.header.last == Character(String(i))
}
)?.cells.append(value: addValue)
// ERROR: Cannot use mutating member on immutable value: function call returns immutable value
You can't just change things inside a set, because of how a (hash) set works. Changing them would possibly change their hash value, making the set into an invalid state.
Therefore, you would have to take the thing you want to change out of the set, change it, then put it back.
if var thing = columns.first(
where: {
$0.header.last == Character(String(i))
}) {
columns.remove(thing)
thing.cells.append(value: addValue)
columns.insert(thing)
}
If the == operator on Column doesn't care about cells (i.e. adding cells to a column doesn't suddenly make two originally equal columns unequal and vice versa), then you could use update instead:
if var thing = columns.first(
where: {
$0.header.last == Character(String(i))
}) {
thing.cells.append(value: addValue)
columns.update(thing)
}
As you can see, it's quite a lot of work, so maybe sets aren't a suitable data structure to use in this situation. Have you considered using an array instead? :)
private var _columns: [Column]
public var columns : [Column] {
get { _columns }
set { _columns = Array(Set(newValue)) }
// or any other way to remove duplicate as described here: https://stackoverflow.com/questions/25738817/removing-duplicate-elements-from-an-array-in-swift
}
You are getting the error because columns might be a set of struct. So columns.first will give you an immutable value. If you were to use a class, you will get a mutable result from columns.first and your code will work as expected.
Otherwise, you will have to do as explained by #Sweeper in his answer.

Difference operation from root

Is there a way to make difference directly from root? I want to do something like this:
difference(){
root();
cube();
}
instead of this:
difference(){
union(){
object1();
object2();
.
.
objectN();
}
cube();
}
You are already on the there. You just need to define root() and cube() as modules like so:
difference(){
root();
cube();
}
module root(){
object1();
object2();
...
}
module cube(){
//some cube definition
}
In the background OpenSCAD will secretly create a union() around every module for you, just as if you wrote:
module xyz(){
union(){
//objects
}
}
So in this example an object root() is created and cube() will be subtracted from this object. By using the module definition you keep your code just as modular as you ask for.
You may also want to have a look at the official docu and cheat sheet here.
difference() module subtracts all other children from the first one. In first snippet, first child is root(), in second first child is union(), and in both cube is subtracted.

average of counts with Laravel 5

We have two classes: Module and Resource, with a module having many resources:
class Module extends Model {
public function resources() {
return $this->hasMany('App\Models\Resource');
}
}
and a resource belonging to a Module:
class Resource extends Model {
public function module() {
return $this->belongsTo('App\Models\Module');
}
}
I need to show a list of all the modules with:
The number of resources for each each module
The average of resources per module
The first one is added to the Module model so it can be used with eager loading:
public function resourcesCount() {
return $this->hasMany('App\Models\Resource')
->selectRaw('module_id, count(*) AS aggregate')
->groupBy('module_id');
}
However, I can't find an efficient and elegant way to calculate the average of the counts calculated by resourcesCount. I know I could iterate through the results of
$modules = Module::with('resourcesCount')->get();
and do it manually, but I feel there's something better out there.
EDIT: forgot to say that I modified the accessor for the resourcesCountAttribute:
public function getResourcesCountAttribute() {
if (!$this->relationLoaded('resourcesCount'))
$this->load('resourcesCount');
$related = $this->getRelation('resourcesCount');
return ($related) ? (int) $related->aggregate : 0;
}
So I can use 'resourcesCount' (See my response), rather than having to use 'resourcesCount.aggregate'.
I found out an acceptable way to do so, using the collection's methods.
// Returns an elloquent collection
$modules = Module::with('resourcesCount')->get();
// counts sums divided by the number of
$avgResources = $modules->sum('resourcesCount') / $modules->count();
The only way would be to do it through iteration or in a separate DB::select() statement, relying on things like GROUP BY and AVERAGE().

In Tritium, is there a way to assign an id based on child number?

I have a table with a series of rows. I want to change them into divs, but maintain (somehow) their positional information. At the moment, this is what I'm doing:
$("./tr[1]") {
add_class("mw_old_row_1")
}
$("./tr[2]") {
add_class("mw_old_row_2")
}
$("./tr") {
name("div")
}
But this isn't ideal because:
It's super-repetitive
I don't know how many rows there are
Is there a way to take the child number and include that in the class I'm assigning?
Yup, you want to make use of the index() function. Below is the example you wrote reworked using index():
$("./tr") {
add_class("mw_old_row_" + index())
name("div")
}
Below is a link with the following example in tritium tester: http://tester.tritium.io/775895b154e8e2ce99e100967299c10d73dbeb91