00001 // Operator2Expr.cpp: implementation of the COperator2Expr class. 00002 /* 00003 * Copyright (c) 1996-2000 Erwin Coumans <[email protected]> 00004 * 00005 * Permission to use, copy, modify, distribute and sell this software 00006 * and its documentation for any purpose is hereby granted without fee, 00007 * provided that the above copyright notice appear in all copies and 00008 * that both that copyright notice and this permission notice appear 00009 * in supporting documentation. Erwin Coumans makes no 00010 * representations about the suitability of this software for any 00011 * purpose. It is provided "as is" without express or implied warranty. 00012 * 00013 */ 00014 // 31 dec 1998 - big update: try to use the cached data for updating, instead of 00015 // rebuilding completely it from left and right node. Modified flags and bounding boxes 00016 // have to do the trick 00017 // when expression is cached, there will be a call to UpdateCalc() instead of Calc() 00018 00019 00020 00021 #include "Operator2Expr.h" 00022 #include "StringValue.h" 00023 #include "VoidValue.h" 00024 //#include "FactoryManager.h" 00026 // Construction/Destruction 00028 00029 COperator2Expr::COperator2Expr(VALUE_OPERATOR op, CExpression *lhs, CExpression *rhs) 00030 : 00031 m_cached_calculate(NULL), 00032 m_op(op), 00033 m_lhs(lhs), 00034 m_rhs(rhs) 00035 /* 00036 pre: 00037 effect: constucts a COperator2Expr with op, lhs and rhs in it 00038 */ 00039 { 00040 00041 } 00042 00043 COperator2Expr::COperator2Expr(): 00044 m_cached_calculate(NULL), 00045 m_lhs(NULL), 00046 m_rhs(NULL) 00047 00048 /* 00049 pre: 00050 effect: constucts an empty COperator2Expr 00051 */ 00052 { 00053 00054 } 00055 00056 COperator2Expr::~COperator2Expr() 00057 /* 00058 pre: 00059 effect: deletes the object 00060 */ 00061 { 00062 if (m_lhs) 00063 m_lhs->Release(); 00064 if (m_rhs) 00065 m_rhs->Release(); 00066 if (m_cached_calculate) 00067 m_cached_calculate->Release(); 00068 00069 } 00070 CValue* COperator2Expr::Calculate() 00071 /* 00072 pre: 00073 ret: a new object containing the result of applying operator m_op to m_lhs 00074 and m_rhs 00075 */ 00076 { 00077 00078 bool leftmodified,rightmodified; 00079 leftmodified = m_lhs->NeedsRecalculated(); 00080 rightmodified = m_rhs->NeedsRecalculated(); 00081 00082 // if no modifications on both left and right subtree, and result is already calculated 00083 // then just return cached result... 00084 if (!leftmodified && !rightmodified && (m_cached_calculate)) 00085 { 00086 // not modified, just return m_cached_calculate 00087 } else { 00088 // if not yet calculated, or modified... 00089 00090 00091 if (m_cached_calculate) { 00092 m_cached_calculate->Release(); 00093 m_cached_calculate=NULL; 00094 } 00095 00096 CValue* ffleft = m_lhs->Calculate(); 00097 CValue* ffright = m_rhs->Calculate(); 00098 00099 ffleft->SetOwnerExpression(this);//->m_pOwnerExpression=this; 00100 ffright->SetOwnerExpression(this);//->m_pOwnerExpression=this; 00101 00102 m_cached_calculate = ffleft->Calc(m_op,ffright); 00103 00104 //if (m_cached_calculate) 00105 // m_cached_calculate->Action(CValue::SETOWNEREXPR,&CVoidValue(this,false,CValue::STACKVALUE)); 00106 00107 ffleft->Release(); 00108 ffright->Release(); 00109 } 00110 00111 return m_cached_calculate->AddRef(); 00112 00113 } 00114 00115 /* 00116 bool COperator2Expr::IsInside(float x, float y, float z,bool bBorderInclude) 00117 { 00118 bool inside; 00119 inside = false; 00120 00121 switch (m_op) 00122 { 00123 case VALUE_ADD_OPERATOR: { 00124 // inside = first || second; // optimized with early out if first is inside 00125 // todo: calculate smallest leaf first ! is much faster... 00126 00127 bool second;//first ;//,second; 00128 00129 //first = m_lhs->IsInside(x,y,z) ; 00130 second = m_rhs->IsInside(x,y,z,bBorderInclude) ; 00131 if (second) 00132 return true; //early out 00133 00134 // second = m_rhs->IsInside(x,y,z) ; 00135 00136 return m_lhs->IsInside(x,y,z,bBorderInclude) ; 00137 00138 break; 00139 } 00140 00141 case VALUE_SUB_OPERATOR: { 00142 //inside = first && !second; // optimized with early out 00143 // todo: same as with add_operator: calc smallest leaf first 00144 00145 bool second;//first ;//,second; 00146 //first = m_lhs->IsInside(x,y,z) ; 00147 second = m_rhs->IsInside(x,y,z,bBorderInclude); 00148 if (second) 00149 return false; 00150 00151 // second space get subtracted -> negate! 00152 //second = m_rhs->IsInside(x,y,z); 00153 00154 return (m_lhs->IsInside(x,y,z,bBorderInclude)); 00155 00156 00157 break; 00158 } 00159 default:{ 00160 assert(false); 00161 // not yet implemented, only add or sub csg operations 00162 } 00163 } 00164 00165 return inside; 00166 } 00167 00168 00169 00170 bool COperator2Expr::IsRightInside(float x, float y, float z,bool bBorderInclude) { 00171 00172 return m_rhs->IsInside(x,y,z,bBorderInclude) ; 00173 00174 } 00175 00176 bool COperator2Expr::IsLeftInside(float x, float y, float z,bool bBorderInclude) { 00177 return m_lhs->IsInside(x,y,z,bBorderInclude); 00178 } 00179 */ 00180 bool COperator2Expr::NeedsRecalculated() { 00181 // added some lines, just for debugging purposes, it could be a one-liner :) 00182 //bool modleft 00183 //bool modright; 00184 assertd(m_lhs); 00185 assertd(m_rhs); 00186 00187 //modright = m_rhs->NeedsRecalculated(); 00188 if (m_rhs->NeedsRecalculated()) // early out 00189 return true; 00190 return m_lhs->NeedsRecalculated(); 00191 //modleft = m_lhs->NeedsRecalculated(); 00192 //return (modleft || modright); 00193 00194 } 00195 00196 00197 00198 CExpression* COperator2Expr::CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks) { 00199 // if both children are 'dead', return NULL 00200 // if only one child is alive, return that child 00201 // if both childresn are alive, return this 00202 00203 00204 bool leftalive = true,rightalive=true; 00205 assertd(false); 00206 assert(m_lhs); 00207 assert(m_rhs); 00208 /* 00209 if (m_cached_calculate) 00210 m_cached_calculate->Action(CValue::REFRESH_CACHE); 00211 00212 CExpression* newlhs = m_lhs->CheckLink(brokenlinks); 00213 CExpression* newrhs = m_rhs->CheckLink(brokenlinks); 00214 00215 if (m_lhs != newlhs) 00216 { 00217 brokenlinks.push_back(new CBrokenLinkInfo(&m_lhs,m_lhs)); 00218 } 00219 00220 if (m_rhs != newrhs) 00221 { 00222 brokenlinks.push_back(new CBrokenLinkInfo(&m_rhs,m_rhs)); 00223 } 00224 00225 00226 00227 m_lhs = newlhs; 00228 m_rhs = newrhs; 00229 00230 if (m_lhs && m_rhs) { 00231 return this; 00232 } 00233 00234 AddRef(); 00235 if (m_lhs) 00236 return Release(m_lhs->AddRef()); 00237 00238 if (m_rhs) 00239 return Release(m_rhs->AddRef()); 00240 / 00241 00242 */ 00243 return Release(); 00244 00245 00246 00247 } 00248 00249 00250 bool COperator2Expr::MergeExpression(CExpression *otherexpr) 00251 { 00252 if (m_lhs) 00253 { 00254 if (m_lhs->GetExpressionID() == CExpression::CCONSTEXPRESSIONID) 00255 { 00256 // cross fingers ;) replace constexpr by new tree... 00257 m_lhs->Release(); 00258 m_lhs = otherexpr->AddRef(); 00259 return true; 00260 } 00261 } 00262 00263 assertd(false); 00264 return false; 00265 } 00266 00267 00268 void COperator2Expr::BroadcastOperators(VALUE_OPERATOR op) 00269 { 00270 if (m_lhs) 00271 m_lhs->BroadcastOperators(m_op); 00272 if (m_rhs) 00273 m_rhs->BroadcastOperators(m_op); 00274 }