ifcopenshell divide elements based on floors - ifc

I am new to the ifcopenshell lib.
I can get elements info by its type,e.g.  
ifcFile = ifcopenshell.open("filepath")
walls = ifcFile.by_type("IfcWall")
slabs = ifcFile.by_type("IfcSlab")
#Then do sth I want
just wondering can we separate elements based on their floor info?
I checked the doc but found nothing. Could someone give me a hint?
link

Just try call "IfcBuildingStorey" type
floors = ifcFile.by_type("IfcBuildingStorey")
for wall in walls:
  contain = element.ContainedInStructure
  if len(contain) > 0:
     if contain[0].RelatingStructure.Name == floors[x]:
         ##your implementation.

Related

What does the `cx` parameter do in Gtag implementations?

I have been debugging an issue with Google Analytics 4 where when a GA4 property is connected to an existing GA3 gtag property, and the request to fetch the JavaScript from GTM contains the parameter cx=c, the resulting JavaScript does not contain the required child container for GA4.
https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXX-1&l=dataLayer&cx=c
The obvious fix is to remove the cx=c parameter and test, or to use another implementation of GA4 directly, but that is not the question.
After seeing the suggested implementation from Google, (e.g. no cx) and this version (with the cx) passed around in various online discussions, Github code and issues, etc. I am trying to figure out what it does. I have searched all Google docs, searched Github and Stack Overflow. I find it referenced with respect to Firebase, but nothing else. Does anyone know what this parameter does, officially?
Short answer: we have no clue what it does.
Longer answer: as you may know, GTM can deploy gtag. Since it can do that, it has the code for generating that function. Although that code is minified, it can still be useful:
var Fn = function (a, b, c) {
if (!En() && !sg(a)) {
var d = c ? "/gtag/js" : "/gtm.js", e = "?id=" + encodeURIComponent(a) + "&l=" + Cd.ba,
f = 0 === a.indexOf("GTM-");
f || (e += "&cx=c"); var g = Dn();
g && (e += "&sign=" + Cd.Xd);
var l = Bn(b, d + e);
if (!l) {
var m = Cd.uc + d; g && bb && f && (m = bb.replace(/^(?:https?:\/\/)?/i, "").split(/[?#]/)[0]);
l = Ri("https://", "http://", m + e)
} rg().container[a] = !0; hb(l)
}
}
See what it does? f indicates whether there is "GTM-" in a or not. And I didn't look up a, but a must be the fetch url. Now, f becomes a binary representation instead of the -1 returned by the indexOf.
Judging from this code, GTM deploys the cx parameter with a very hardcoded value whenever it deploys something that is not GTM, I imagine, from it's own family of fetch urls, which can include GTM itself. Why GTM doesn't want cx=c for its code? No idea. I have it loaded with it more often than without.
But here's another place where it's used:
Gn = function (a, b) {
var c; if (c = !En()) c = !rg().destination.hasOwnProperty(a); if (c) {
var d = "/gtag/destination?id=" + encodeURIComponent(a) + "&l=" + Cd.ba + "&cx=c";
Dn() && (d += "&sign=" + Cd.Xd); var e = Bn(b, d); e || (e = Ri("https://", "http://", Cd.uc + d)); rg().destination[a] = !0; hb(e)
}
};
En() is always false. It looks like it's some weird remnants from GTM's dev environments. Poor env variables management on GTM's side, but no one cares.
I stopped looking into the Gn function at this point. But if you want to persist digging, you're free to do so. I have a sneaking suspicion that the cx parameter does exactly no difference on the side of the consumer (our side). It may be something beneficial for Google's dev team, but I doubt it. Params, hardcoded like this are rarely a good idea. Looks to me like a fluke.

Google Earth Engine: Image intersection and inverse intersection

I am new to Google Earth Enginge and I struggle to bring together two images in Google Earth Engine to get the areas which are in both images and the areas which are only part of one image to show forest cover change (loss, gain, no change).
My code so far which seems to at least display what I want by stacking the images above each other:
var treeCanopyCoverVis = {
min: 0.0,
max: 100.0,
palette: ['ffffff', 'afce56', '5f9c00', '0e6a00', '003800'],
};
var forest2000 = ee.ImageCollection('NASA/MEASURES/GFCC/TC/v3')
.filterDate('2000-01-01', '2000-12-31')
.select('tree_canopy_cover')
.reduce(ee.Reducer.mean());
var forest2000_ab60 = forest2000.gt(60).selfMask();
Map.addLayer(forest2000_ab60, {palette: '#d80078'}, 'Loss');
var forest2015 = ee.ImageCollection('NASA/MEASURES/GFCC/TC/v3')
.filterDate('2015-01-01', '2015-12-31')
.select('tree_canopy_cover')
.reduce(ee.Reducer.mean());
var forest2015_ab60 = forest2015.gt(60).selfMask();
Map.addLayer(forest2015_ab60, {palette: '#ebb13a'}, 'Gain');
// var loss = forest2015_ab60.intersection(forest2000_ab60);
print(forest2015_ab60);
print(forest2000_ab60);
var remain = forest2015_ab60.and(forest2000_ab60);
Map.addLayer(remain, {palette: '#746d75'}, 'Remain');
With this code the gain still includes the remain part and the loss part also still includes the remain part. I need kind of the subtraction. All functions I now tried result in errors. I appreciate any help!
How my current result looks:
I could somehow solve it with try and error.
The code:
var forest2000 = ee.ImageCollection('NASA/MEASURES/GFCC/TC/v3')
.filterDate('2000-01-01', '2000-12-31')
.select('tree_canopy_cover')
.reduce(ee.Reducer.mean());
var forest2015 = ee.ImageCollection('NASA/MEASURES/GFCC/TC/v3')
.filterDate('2015-01-01', '2015-12-31')
.select('tree_canopy_cover')
.reduce(ee.Reducer.median());
var gain = forest2000.lt(60).and(forest2015.gt(60));
Map.addLayer(gain.selfMask(), {palette: '#ebb13a'}, 'gain');
var loss = forest2000.gt(60).and(forest2015.lt(60));
Map.addLayer(loss.selfMask(), {palette: '#d80078'}, 'loss');
var nochange = forest2000.gt(60).and(forest2015.gt(60));
Map.addLayer(nochange.selfMask(), {palette: '#746d75'}, 'no change');

Kusto: Permission based display of columns

I am trying to access function parameters within the 'case' statement in that function and displaying data/"filtered" based on the permission flag..Is it possible?
Usecase: TypeCast the value based on the columnType and check if the user has the permission to view the column based on which you display either the value or say something like "filtered"
Here is what I tried
function rls_columnCheck
.create-or-alter function rls_columnCheck(tableName:string, columnName: string, value:string, columnType:string, IsInGroupPII:bool, IsInGroupFinance:bool) {
let PIIColumns = rls_getTablePermissions(tableName, "PII");
let FinanceColumns = rls_getTablePermissions(tableName, "Finance");
let val= case(columnType=="bool", tobool(value),
columnType=="datetime", todatetime(value),
columnType=="int", toint(value),
value);
iif(columnName in (PIIColumns),
iif(columnName in (FinanceColumns),
iif(IsInGroupPII == true and IsInGroupFinance == true,
val,
"filtered"), // PII True, Fin True
iif(IsInGroupPII == true,
val,
"filtered") // PII True, Fin False
),
iif(columnName in (FinanceColumns),
iif(IsInGroupFinance == true,
val,
"filtered"), // PII False, Fin True
val // PII False, Fin False
)
);
}
Error:
Call to iff(): #then data type (int) must match the #else data type (string)
val in your function must have a single and well-defined data type, that is known at "compile" time of the query.
you can't have different cases, where in each it has a different type (bool, datetime, int, string - in your case statement) - hence the error.
if it makes sense in your use case, you can try to always have val typed as string.
This is not a good approach to use RLS because this will actually cause the engine to run a function for every column of every record. It has many downsides:
Performance of displaying the table’s contents (even if you have full permissions)
Queries on the table won’t benefit from the indexes Kusto stores (suppose you query PermissionTesting2 | where Col1 has “blablabla” - instead of checking the index for “blablabla”, the engine will have to scan all the data, because it has to apply a function for every single cell)
A better approach is to do something like this:
let UserCanSeePII = current_principal_is_member_of('aadgroup=group1#domain.com');
let UserCanSeeFinance = current_principal_is_member_of('aadgroup=group2#domain.com');
let ResultWithPII = YourTable | where UserCanSeePII and (not UserCanSeeFinance) | where ... | extend ...;
let ResultWithFinance = YourTable | where UserCanSeeFinance and (not UserCanSeePII) | where ... | extend ...;
let ResultWithPIIandFinance = YourTable | where UserCanSeeFinance and UserCanSeePII | where ... | extend ...;
let ResultWithoutPIIandFinance = YourTable | where (not UserCanSeePII) and (not UserCanSeeFinance) | where ... | extend ...;
union ResultWithPII, ResultWithFinance, ResultWithPIIandFinance, ResultWithoutPIIandFinance

get directions about 50meters out

I have a api3 map that generates the pointer in the correct place for a bed and breakfast using
var orchards = new google.maps.LatLng(52.512565,-2.7595);
I want to add in the "Get directions" and its working ok except that its ending at a slightly different place. The directions are ending at a house about 100meters down the road - not quite where the lat/long for the map are. The postcode for the guest house is SY6 7DQ but the directions end at SY6 7DG
How can I get the directions to end in the right place.
You can see what I mean here : http://www.dev.ee-web.co.uk/orchards/index.php?option=com_content&view=article&id=6&Itemid=106
Here's the function that I am using::
function calcRoute() {
directionsVisible=true;
// alter print text
document.getElementById('printMe').innerHTML = " Print directions";
// remove marker
marker.setMap(null);
var start = document.getElementById("startFrom").value;
var end = "52.512565,-2.7595";
var request = {
origin:start,
destination:end,
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
I tried putting the correct postcode into google maps, and numbers produced still point to the wrong place.
I'd really appreciate any help
Thanks
It looks like the directions are very accurate when you specify a LatLng on the road. My guess is the original result was unsatisfactory because the marker is off the road.
Go to this page and click on the road where you want the directions to end and copy the latLng value from the right. Paste into your var end = ... I recommend saving the precision.
https://files.nyu.edu/hc742/public/googlemaps/geocodeUK.html

Ghost objects - bulletphysics

I'm trying to implement a simple ghost object in bulletphysics, this is how I create the ghost objects:
btGhostPairCallback* ghostCall = new btGhostPairCallback();
world->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(ghostCall);
btGhostObject* ghostObj = new btGhostObject();
btCollisionShape* shape = new btBoxShape(btVector3(ofGetWidth()+1000, ofGetHeight()+1000, 50));
ghostObj->setCollisionShape(shape);
btTransform trans;
trans.setIdentity();
trans.setOrigin(btVector3(0,0,-500));
ghostObj->setWorldTransform(trans);
ghostObj->setCollisionFlags( btCollisionObject::CF_NO_CONTACT_RESPONSE);
world->addCollisionObject(ghostObj,btBroadphaseProxy::SensorTrigger,btBroadphaseProxy::AllFilter & ~btBroadphaseProxy::SensorTrigger);
and this is how to try to find the collision:
btCollisionObject* obj = world->getCollisionObjectArray()[j];
btRigidBody* body = btRigidBody::upcast(obj);
btAlignedObjectArray < btCollisionObject* > objsInsidePairCachingGhostObject;
btAlignedObjectArray < btCollisionObject* >* pObjsInsideGhostObject = NULL;
btGhostObject* ghost = btGhostObject::upcast(obj);
if(ghost){
objsInsidePairCachingGhostObject.resize(0);
pObjsInsideGhostObject = &ghost->getOverlappingPairs();
cout << ghost->getNumOverlappingObjects() << endl;
but I always get a response that all my world objects are in collision with the ghost object.
Anyone can help me to get a functional simple ghost object?
thanks
From what little I understand of the GhostObject, you're overriding its default collision flags. Try changing this line
ghostObj->setCollisionFlags( btCollisionObject::CF_NO_CONTACT_RESPONSE);
to:
ghostObj->setCollisionFlags( ghostObj->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);
HTH
While I agree that the collision flags should be set properly by adding the new flag to the existing set of flags I'd also like to point out that the parameter to btBoxShape is a btVector3 that defines the half-extents of the object. That means the width, height, and length are actually twice as large as those parameters.

Resources