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 }