How to flatten a Ngon base on average height of each points

   1849   4   0
User Avatar
Member
3 posts
Joined: Jan. 2021
Offline
I have created some buildings base on osm curves from mapbox.



As you can see, the roof is not flat.
Is there a proper way to flatten the roof(up) surface(base on the average height of roof surface's points) and keep the bottom as itself.
Thank you!!
Edited by martiancomeon - Jan. 14, 2021 19:58:11

Attachments:
2021-01-14 22_26_51-C__Users_tin1630_ONEDRI~1_Desktop_WIP_houdini_210114_osm_map_01_hip_osm_map_2101.jpg (58.3 KB)
2021-01-14 22_28_13-C__Users_tin1630_ONEDRI~1_Desktop_WIP_houdini_210114_osm_map_01_hip_osm_map_2101.jpg (11.8 KB)

User Avatar
Member
472 posts
Joined: July 2005
Offline
Hi,

it seems, that all roofs are represented by one primitive, which is part of the "extrudeFront" group. You can loop over the primpoints for each prim, take the average and write the y-component back to original points. This should be doing, what you already described.
Check the modification of your file.
Edited by Aizatulin - Jan. 14, 2021 13:01:04

Attachments:
osm_map_2101144_b_mod.hipnc (543.4 KB)

User Avatar
Member
3 posts
Joined: July 2018
Offline
maybe you can do this:
vector min;
vector max;
getbbox(min,max);

 @P.`chs("axis")` = max.y;

running in point mode
just put the primitives you want to flatten in group of the vex snippet


For lots of buildings i think this will be faster:

Run in primitive mode:
gives you 3 modes: avg, max, min

//aireverie n-gon flatten
int a[] = primpoints(0, @primnum);
vector b[];
float c[];
vector newP;

for(int i=0; i<len(a); i++) {
    newP = point(0, "P", a[i]);
    push(b, newP);
    push(c, newP.y);
}

float min = min(c);
float max = max(c);
float avg = avg(c);
for(int i=0; i<len(b); i++) {
    newP = b[i];
    if(chi("mode")==0){
        newP.y = min;
        setpointattrib(0, "P", a[i], newP);
    
    } else if(chi("mode")==1) {
        newP.y = avg;
        setpointattrib(0, "P", a[i], newP);
    } else if(chi("mode")==2) {
        newP.y = max;
        setpointattrib(0, "P", a[i], newP);
    }
    
}
Edited by aireverie - Jan. 14, 2021 13:10:33
User Avatar
Member
3 posts
Joined: Jan. 2021
Offline
Aizatulin
Hi,

it seems, that all roofs are represented by one primitive, which is part of the "extrudeFront" group. You can loop over the primpoints for each prim, take the average and write the y-component back to original points. This should be doing, what you already described.
Check the modification of your file.
Thank you so much for you answer!! I have figured it out. Thank you again!
User Avatar
Member
3 posts
Joined: Jan. 2021
Offline
aireverie
maybe you can do this:
vector min;
vector max;
getbbox(min,max);

 @P.`chs("axis")` = max.y;

running in point mode
just put the primitives you want to flatten in group of the vex snippet


For lots of buildings i think this will be faster:

Run in primitive mode:
gives you 3 modes: avg, max, min

//aireverie n-gon flatten
int a[] = primpoints(0, @primnum);
vector b[];
float c[];
vector newP;

for(int i=0; i<len(a); i++) {
    newP = point(0, "P", a[i]);
    push(b, newP);
    push(c, newP.y);
}

float min = min(c);
float max = max(c);
float avg = avg(c);
for(int i=0; i<len(b); i++) {
    newP = b[i];
    if(chi("mode")==0){
        newP.y = min;
        setpointattrib(0, "P", a[i], newP);
    
    } else if(chi("mode")==1) {
        newP.y = avg;
        setpointattrib(0, "P", a[i], newP);
    } else if(chi("mode")==2) {
        newP.y = max;
        setpointattrib(0, "P", a[i], newP);
    }
    
}
Thank you very much!!your are so nice! I have learned a lot, Thank you!
  • Quick Links