00001 /* 00002 File: HRLink.cc 00003 00004 Function: See header file 00005 00006 Author(s): Andrew Willmott 00007 00008 Copyright: (c) 1997-2000, Andrew Willmott 00009 00010 */ 00011 00012 #include "HRLink.h" 00013 #include "HRElem.h" 00014 #include "HierRad.h" 00015 #include "gcl/Draw.h" 00016 00017 #ifdef RAD_VIS 00018 #include "gcl/Forms.h" 00019 #endif 00020 00021 #define DBG_COUT if (0) cerr 00022 #define DBG2_COUT if (0) cerr 00023 00024 enum HLFlags 00025 { 00026 hlGotVis = 0x80 00027 }; 00028 00029 // --- HRLink methods --------------------------------------------------------- 00030 00031 00032 HRLink::HRLink() : from(0), to(0), visibility(0.0), flags() 00033 { 00034 } 00035 00036 RefChoice HRLink::RefineOracle() 00037 /* This drives the refinement strategy. */ 00038 { 00039 GCLReal w, err; 00040 Vector temp; 00041 GCLReal fromProj, toProj; 00042 GCLReal kAError = gRadControl->kAError; 00043 GCLReal kFError = gRadControl->kFError; 00044 00045 DBG2_COUT << "REFINE ORACLE: test link from " << from->id << ':' << 00046 from->flags << " to " << to->id << ':' << to->flags << endl; 00047 00048 #ifdef RAD_STEP_VIS 00049 if (visibility > 0.0 && visibility < 1.0) 00050 w = gRadControl->visError; 00051 else 00052 w = 1.0; 00053 #else 00054 w = abs(1.0 - 2 * visibility) * (1 - gRadControl->visError) + gRadControl->visError; 00055 #endif 00056 00057 if (gRadControl->useBF) 00058 err = BFAError(); 00059 else 00060 err = Error(); 00061 00062 DBG2_COUT << "error = " << err << ", w = " << w << endl; 00063 00064 Expect(err >= 0.0, "negative link error???"); 00065 if (err < 0.0) err = 0.0; 00066 if (err < kFError * w) 00067 return(kSubNone); 00068 00069 if (to == from) 00070 return(kSubBoth); 00071 00072 // Find projected area of the two patches 00073 #ifdef RAD_PROJ_AREA_REF 00074 temp = safe_norm(to->EltCentre() - from->EltCentre()); 00075 toProj = to->EltProjArea(-temp); 00076 fromProj = from->EltProjArea(temp); 00077 #else 00078 toProj = to->EltArea(); 00079 fromProj = from->EltArea(); 00080 #endif 00081 00082 DBG2_COUT << "refining : " << fromProj << " -> " << toProj 00083 << " : " << from->IsCluster() << ":" << to->IsCluster() << endl; 00084 00085 // Decide which patch to subdivide... 00086 00087 if (gRadControl->favourReceiver * toProj > fromProj) 00088 if (to->EltArea() < kAError) 00089 return(kSubNone); 00090 else 00091 return(kSubTo); 00092 else 00093 if (from->EltArea() < kAError) 00094 return(kSubNone); 00095 else 00096 return(kSubFrom); 00097 } 00098 00099 Bool HRLink::MakeLink( 00100 HRElem *fromElem, 00101 HRElem *toElem, 00102 HRLink *parentLink, 00103 Bool forceVisReuse 00104 ) 00108 { 00109 Assert(fromElem != 0 && toElem != 0, 00110 "(HRLink::MakeLink) null element in to/from"); 00111 00112 from = fromElem; 00113 to = toElem; 00114 00115 if ((from == to) && from->IsPatch()) 00116 return(false); 00117 00118 if (to->EltRho() == vl_0) 00119 return(false); 00120 00121 if (!CalcTransport()) 00122 return(false); 00123 00124 if (!gRadControl->visInQuad) 00125 return(CalcVisibility(parentLink, forceVisReuse)); 00126 00127 return(true); 00128 } 00129 00130 Bool HRLink::CalcVisibility(HRLink *parentLink, Bool forceVisReuse) 00133 { 00134 if (parentLink && (forceVisReuse || !NeedVisibility(parentLink))) 00135 visibility = parentLink->visibility; 00136 else 00137 visibility = from->EltVis(to); 00138 00139 // for the moment, we can't be absolutely positive there is 00140 // no transfer 'cause we're sampling, so always return true. 00141 return(true); 00142 } 00143 00144 HRLink *HRLink::CreateSubLink(HRElem *fromElem, HRElem *toElem) 00145 { 00146 HierRad *method = (HierRad*) gRadControl->radObject; 00147 00148 if (method->linksCreated++ > method->linksCreatedLast + 500) 00149 { 00150 if (gRadControl->stop || method->Stage(7)) 00151 return(0); 00152 00153 method->linksCreatedLast = method->linksCreated; 00154 } 00155 00156 HRLink *result = New(); 00157 00158 if (result->MakeLink(fromElem, toElem, this)) 00159 { 00160 DBG2_COUT << "made new link: " << fromElem->id << " " << toElem->id 00161 << " vis = " << result->visibility << endl; 00162 return(result); 00163 } 00164 00165 DBG_COUT << "link REDACTED" << endl; 00166 FreeLink(result); 00167 00168 return(0); 00169 } 00170 00171 Void HRLink::Print(ostream &s) 00172 { 00173 s << "[" << from << "->" << to << "] "; 00174 } 00175 00176 Void HRLink::DrawLink(Renderer &r, 00177 GCLReal left, GCLReal top, 00178 GCLReal right, GCLReal bottom, 00179 GCLReal weight 00180 ) 00181 { 00182 r.C(cCyan); 00183 PaintRect(r, Coord(left, bottom), Coord(right, top)); 00184 } 00185 00186 ostream &operator << (ostream &s, HRLink &rl) 00187 { 00188 rl.Print(s); 00189 00190 return(s); 00191 } 00192 00193 Bool HRLink::NeedVisibility(HRLink *parentLink) 00194 { 00195 return( 00196 (to->EltArea() > gRadControl->forceVisReuseArea) || 00197 to->IsCluster() || from->IsCluster() || 00198 (parentLink->visibility > 0.0 && parentLink->visibility < 1.0) 00199 ); 00200 } 00201 00202 Void HRLink::DebugInfo() 00203 { 00204 cout << "=== link flags/vis: " << Int(flags) << " " << visibility << endl; 00205 cout << "source radiosity: " << from->B_Coeffs()[0] << endl; 00206 cout << "transport strength: " << Strength() << endl; 00207 cout << "power error: " << BFAError() << endl; 00208 } 00209 00210 Void HRLink::FreeLink(HRLink *oldLink) 00211 { 00212 delete oldLink; 00213 }