/* bounder.inc * * "not a cad, just a bounder." ;-) * * macro Bounder(obj, optional res) * calculate an object's required bounding box, compare it to the * existing, and suggest tighter bounds where possible. * the optional second argument, resolution, determines the number * of probes/scans per POV unit; multiples of 5, range: 5,..,10000. * the pretty-print output goes to the '#debug' stream. * returns (expands to) nothing. * * version: 201910. * */ #ifndef (bounder_include_temp) #declare bounder_include_temp = version; #version 3.8; #ifdef (View_POV_Include_Stack) #debug "including bounder.inc\n" #end #include "shapes.inc" /* -----[helpers]----------------------------------------------------------- */ /* legal resolutions multiples of 5, range: 5,..,10000 */ #macro bndr_checkRes(r_) #local v_ = <1,1,1> * r_; /* "promote" */ #if (mod(v_.x,5) | mod(v_.y,5) | mod(v_.z,5)) #local e_ = 1; #elseif (5 > v_.x | 5 > v_.y | 5 > v_.z) #local e_ = 1; #elseif (10000 < v_.x | 10000 < v_.y | 10000 < v_.z) #local e_ = 1; #end #ifdef (local.e_) #error concat("oops, bad resolution <",vstr(3,v_,",",0,0),">, ", "must be divisible by 5, range: 5,..,10000.\n") #end v_ #end /* separator hyphens */ #macro bndr_hyphens(n_) #local s_ = ""; #for (i_,1,n_) #local s_ = concat(s_,"-"); #end s_ #end /* space fill, right align string */ #macro bndr_strFmt(s_) #local w_ = 28; /* cf b_ */ #local n_ = strlen(s_); #if (w_ <= n_) #local rtn_ = s_; #else #local b_ = " "; /* 30 spaces */ #local rtn_ = concat(substr(b_,1,(w_-n_)),s_); #end rtn_ #end /* print 3-vector */ #macro bndr_emit3V(s_,v_,p_) #local fs_ = bndr_strFmt(s_); #debug concat(fs_,": <",vstr(3,v_,", ",0,p_),">\n") #end /* print string value */ #macro bndr_emitStr(s_,v_) #local fs_ = bndr_strFmt(s_); #debug concat(fs_,": ",v_,"\n") #end /* print int/float value */ #macro bndr_emitVal(s_,v_,p_) #local fs_ = bndr_strFmt(s_); #debug concat(fs_,": ",str(v_,0,p_),"\n") #end /* print assessment of BB fit */ #macro bndr_emitGrade(dims_,bbl_,bbu_) #local ldiff_ = ; #local udiff_ = ; #local pc5_ = dims_ * .05; #local pc1_ = dims_ * .01; #debug concat(" ",bndr_hyphens(20),"\n") #debug concat(bndr_strFmt("diff lower bound"), ": ", vstr(3,ldiff_,",",0,8),"\n") #debug concat(bndr_strFmt("diff upper bound"), ": ", vstr(3,udiff_,",",0,8),"\n") #if ((pc1_.x >= ldiff_.x) & (pc1_.y >= ldiff_.y) & (pc1_.z >= ldiff_.z)) #debug concat(" object bounding box is (near) optimal.","\n") #elseif ((pc5_.x >= ldiff_.x) & (pc5_.y >= ldiff_.y) & (pc5_.z >= ldiff_.z)) #debug concat(" object bounding box is good, under 5% \"slack\".","\n") #else #debug concat(" object bounding box has at least 5% \"slack\".","\n") #end #end /* -----["main"]------------------------------------------------------------ */ #macro Bounder(obj_,optional res_) #debug concat(bndr_hyphens(10),"[Bounder info]",bndr_hyphens(48),"\n") #ifndef (local.res_) #local res_ = <1,1,1> * 50; /* low-ish */ #else #local res_ = bndr_checkRes(res_); #end bndr_emit3V("resolutions (per POV unit)",res_,0) /* place object at origin */ bndr_emit3V("object \"as is\" (BB) min",min_extent(obj_),6) bndr_emit3V("object \"as is\" (BB) max",max_extent(obj_),6) #local o_ = object {Align_Object(obj_,<-1,-1,-1>,<0,0,0>)}; #local dims_ = max_extent(o_) - min_extent(o_); bndr_emit3V("object aligned (BB) max",dims_,6) /* calc N steps + increments */ #local nstep_ = ; #local incr_ = ; /* three scans by axis, into both "faces" of each. * find last point(s) outside of object. */ #local bbl_ = <0,0,0>; #local bbu_ = dims_; /* scan axis 'X', face ZY */ bndr_emitVal("axis 'X' scan resolution",nstep_.x,0) bndr_emitVal("probes per face",(nstep_.z*nstep_.y),0) bndr_emitVal("scan axis increment",incr_.x,8) bndr_emitVal("face col increment",incr_.z,8) bndr_emitVal("face row increment",incr_.y,8) bndr_emitStr(bndr_hyphens(1),"...scanning...") /* flags control negative/positive scan directions */ #local nflag_ = 1; #local pflag_ = 1; #local cntx_ = 0; #for (n_,0,nstep_.x-1) #if (pflag_) #for (j_,0,nstep_.y-1) #for (i_,0,nstep_.z-1) #local p_ = ; #if (inside(o_,p_)) #local pflag_ = 0; #end #local cntx_ = cntx_ + 1; #end #end /* no hit? record */ #if (pflag_) #local bbl_ = ; #end #end #if (nflag_) #for (j_,0,nstep_.y-1) #for (i_,0,nstep_.z-1) #local p_ = ; #if (inside(o_,p_)) #local nflag_ = 0; #end #local cntx_ = cntx_ + 1; #end #end #if (nflag_) #local bbu_ = ; #end #end #if (!(nflag_ | pflag_)) #break #end #end bndr_emitVal("total # probes",cntx_,0) /* scan axis 'Y', face XZ */ bndr_emitVal("axis 'Y' scan resolution",nstep_.y,0) bndr_emitVal("probes per face",(nstep_.x*nstep_.z),0) bndr_emitVal("scan axis increment",incr_.y,8) bndr_emitVal("face col increment",incr_.x,8) bndr_emitVal("face row increment",incr_.z,8) bndr_emitStr(bndr_hyphens(1),"...scanning...") #local nflag_ = 1; #local pflag_ = 1; #local cnty_ = 0; #for (n_,0,nstep_.y-1) #if (pflag_) #for (j_,0,nstep_.z-1) #for (i_,0,nstep_.x-1) #local p_ = ; #if (inside(o_,p_)) #local pflag_ = 0; #end #local cnty_ = cnty_ + 1; #end #end #if (pflag_) #local bbl_ = ; #end #end #if (nflag_) #for (j_,0,nstep_.z-1) #for (i_,0,nstep_.x-1) #local p_ = ; #if (inside(o_,p_)) #local nflag_ = 0; #end #local cnty_ = cnty_ + 1; #end #end #if (nflag_) #local bbu_ = ; #end #end #if (!(nflag_ | pflag_)) #break #end #end bndr_emitVal("total # probes",cnty_,0) /* scan axis 'Z', face XY */ bndr_emitVal("axis 'Z' scan resolution",nstep_.z,0) bndr_emitVal("probes per face",(nstep_.x*nstep_.y),0) bndr_emitVal("scan axis increment",incr_.z,8) bndr_emitVal("face col increment",incr_.x,8) bndr_emitVal("face row increment",incr_.y,8) bndr_emitStr(bndr_hyphens(1),"...scanning...") #local nflag_ = 1; #local pflag_ = 1; #local cntz_ = 0; #for (n_,0,nstep_.z-1) #if (pflag_) #for (j_,0,nstep_.y-1) #for (i_,0,nstep_.x-1) #local p_ = ; #if (inside(o_,p_)) #local pflag_ = 0; #end #local cntz_ = cntz_ + 1; #end #end #if (pflag_) #local bbl_ = ; #end #end #if (nflag_) #for (j_,0,nstep_.y-1) #for (i_,0,nstep_.x-1) #local p_ = ; #if (inside(o_,p_)) #local nflag_ = 0; #end #local cntz_ = cntz_ + 1; #end #end #if (nflag_) #local bbu_ = ; #end #end #if (!(nflag_ | pflag_)) #break #end #end bndr_emitVal("total # probes",cntz_,0) bndr_emitGrade(dims_,bbl_,bbu_) #debug concat(bndr_hyphens(72),"\n") #end #version bounder_include_temp; #end /* --------------------------------------------------------------- * * the content above is covered by the GPLv3+, see file COPYING. * * copyright (c) 2019 jr . * * all rights reserved. * * --------------------------------------------------------------- */