int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QSqlDatabase db1(); { QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "connection_name"); db.setDatabaseName(":memory:"); db.open(); db.transaction(); QSqlQuery q("CREATE TABLE t (i INTEGER)", db); q.prepare("INSERT INTO t (i) VALUES(?)"); q.addBindValue(42); q.exec(); db.commit(); db.transaction(); q.setForwardOnly(true); q.setForwardOnly(false); q.exec("SELECT * FROM t"); q.first(); int value = q.value(0).toInt(); Q_ASSERT(value == 42); q.last(); q.finish(); } QSqlDatabase::removeDatabase("connection_name"); QTimer::singleShot(500, qApp, SLOT(quit())); return app.exec(); }
double DoubleBits::maximumCommonMantissa(double d1, double d2) { if (d1==0.0 || d2==0.0) return 0.0; DoubleBits db1(d1); DoubleBits db2(d2); if (db1.getExponent() != db2.getExponent()) return 0.0; int maxCommon=db1.numCommonMantissaBits(db2); db1.zeroLowerBits(64-(12+maxCommon)); return db1.getDouble(); }
int main(){ chdir(QUERY_DATA_PATH); EnvDB *env = new EnvDB(); env->open(); BDBOpe db1(env->getEnv(), DB1); BDBOpe db2(env->getEnv(), DB2); Operator *o1, *o2, *o3, *o4; db1.open(); db2.open(); TABLE_REC tableRec1, tableRec2; tableRec1.tableID = DB1_tableID; tableRec1.attriNum = DB1_attriNum; tableRec2.tableID = DB2_tableID; tableRec2.attriNum = DB2_attriNum; ATTRIBUTE_REC attriRec1[tableRec1.attriNum]; ATTRIBUTE_REC attriRec2[tableRec2.attriNum]; AttributeManager AM(env->getEnv()); AM.getForTableID(tableRec1, attriRec1); AM.getForTableID(tableRec2, attriRec2); /* JOin target */ OPERATION_NODE pn[2]; pn[0].tableID = 15; pn[0].attributeID = 1; pn[0].option = 0; pn[1].tableID = 16; pn[1].attributeID = 1; pn[1].option = 0; JOIN_OPERATION_NODE jpn[1]; jpn[0].rightNode = pn[0]; jpn[0].leftNode = pn[1]; /* ============ */ o1 = new Scan_U2(&db1, attriRec1, DB1_attriNum, 1000000, 10); ((Scan_U2 *)o1)->storeData(); o2 = new Scan_U2(&db2, attriRec2, DB2_attriNum, 1000000, 10); ((Scan_U2 *)o2)->storeData(); o3 = new MargeJoin(o1, o2 , jpn, 1); o4 = new OutPut(TIME_OUT); o4->setPreOperator(o3); o4->init(env->getEnv()); o4->exec(); }
int main(int argc, char *argv[]) { // create an embedded R instance RInside R(argc, argv); // expose the "swapFoo" and "addFoo" functions in the global environment R["swapFoo"] = Rcpp::InternalFunction( &swapFoo ); R["addFoo"] = Rcpp::InternalFunction( &addFoo ); // We can also expose C++11's std::function, for example to grant access to these three "databases" FooDatabase db1(1), db2(2), db3(3); // All data from DB1 can be queried std::function< std::unique_ptr<Foo>(int) > queryDB1 = std::bind(&FooDatabase::queryFoo, std::ref(db1), std::placeholders::_1); R["queryDB1"] = Rcpp::InternalFunction( queryDB1 ); // DB2 shall only be queried with id=42 std::function< std::unique_ptr<Foo>() > queryDB2 = std::bind(&FooDatabase::queryFoo, std::ref(db2), 42); R["queryDB2"] = Rcpp::InternalFunction( queryDB2 ); // For DB3, let's do some more complicated permission checks. That's a good excuse to use a lambda. std::function< std::unique_ptr<Foo>(int) > queryDB3 = [&db3] (int id) -> std::unique_ptr<Foo> { if (id < 0 || id > 20) throw "id out of allowed range"; return db3.queryFoo(id); }; R["queryDB3"] = Rcpp::InternalFunction( queryDB3 ); std::unique_ptr<Foo> result = R.parseEvalNT( "foo1 = queryDB1(20);" //"print(foo1);" // a=1, b=20 "foo2 = queryDB2();" //"print(foo2);" // a=2, b=42 "foo3 = queryDB3(10);" //"print(foo3);" // a=3, b=10 "foo1 = swapFoo(foo1);" //"print(foo1);" // a=20, b=1 "foo = addFoo(foo1, addFoo(foo2, foo3));" //"print(foo);" // a=25, b=53 "foo;" // return the object ); std::cout << " Got result a=" << result->a << ", b=" << result->b << std::endl; std::cout << " Expected a=25, b=53" << std::endl; }
// // Blob tests. // Encodes and decodes Db and Key blobs and all that jazz. // void blobs() { printf("* Database blob encryption test\n"); ClientSession ss(CssmAllocator::standard(), CssmAllocator::standard()); DbTester db1(ss, "/tmp/one", NULL, 60, true); DbTester db2(ss, "/tmp/two", NULL, 30, false); // encode db1, purge it, decode it again CssmData dbBlob; ss.encodeDb(db1, dbBlob); DbHandle db1a = ss.decodeDb(db1.dbId, &nullCred, dbBlob); ss.releaseDb(db1); if (db1 == db1a) detail("REUSED DB HANDLE ON DECODEDB (probably wrong)"); DBParameters savedParams; ss.getDbParameters(db1a, savedParams); assert(savedParams.idleTimeout == db1.params.idleTimeout); assert(savedParams.lockOnSleep == db1.params.lockOnSleep); detail("Database encode/decode passed"); // make sure the old handle isn't valid anymore try { ss.getDbParameters(db1, savedParams); printf("OLD DATABASE HANDLE NOT PURGED (possibly wrong)\n"); } catch (const CssmCommonError &err) { detail(err, "old DB handle rejected"); } // open db1 a second time (so now there's two db handles for db1) DbHandle db1b = ss.decodeDb(db1.dbId, &nullCred, dbBlob); // release both db1 handles and db2 ss.releaseDb(db1a); ss.releaseDb(db1b); ss.releaseDb(db2); }
static MCONTACT FindContactByUrl(HWND hwndDlg) { MCONTACT res = NULL; TCHAR urltext[300], titlebartxt[300]; int contactcount = 0; GetDlgItemText(hwndDlg, IDC_OPEN_URL, urltext, _countof(urltext)); GetWindowText(hwndDlg, titlebartxt, _countof(titlebartxt)); for (MCONTACT hContact = db_find_first(MODULENAME); hContact != NULL; hContact = db_find_next(hContact, MODULENAME)) { ptrT db1( db_get_tsa(hContact, MODULENAME, URL_KEY)); ptrT db2( db_get_tsa(hContact, MODULENAME, PRESERVE_NAME_KEY)); if (!mir_tstrcmp(urltext, db1) && !mir_tstrcmp(titlebartxt, db2)) { contactcount++; if (contactcount > 1) { MessageBox(NULL, TranslateT("ERROR: You have two or more Webview contacts with the same URL and contact name."), _T(MODULENAME), MB_OK); return NULL; } res = hContact; } } return res; }
// // Database tests. // Database locks/unlocks etc. // void databases() { printf("* Database manipulation test\n"); CssmAllocator &alloc = CssmAllocator::standard(); ClientSession ss(alloc, alloc); AutoCredentials pwCred(alloc); StringData passphrase("two"); StringData badPassphrase("three"); pwCred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK, new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), new(alloc) ListElement(passphrase)); pwCred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), new(alloc) ListElement(badPassphrase)); // pwCred = (NEW: two, OLD: three) DbTester db1(ss, "/tmp/one", NULL, 30, true); DbTester db2(ss, "/tmp/two", &pwCred, 60, false); // db2.passphrase = two // encode db1 and re-open it CssmData dbBlob; ss.encodeDb(db1, dbBlob); DbHandle db1b = ss.decodeDb(db1.dbId, &nullCred, dbBlob); if (db1b == db1.dbRef) detail("REUSED DB HANDLE ON DECODEDB (probably wrong)"); // open db1 a third time (so now there's three db handles for db1) DbHandle db1c = ss.decodeDb(db1.dbId, &nullCred, dbBlob); // lock them to get started ss.lock(db1); ss.lock(db2); // unlock it through user prompt("unlock"); ss.unlock(db1); prompt(); ss.unlock(db1b); // 2nd unlock should not prompt ss.lock(db1c); // lock it again prompt("unlock"); ss.unlock(db1); // and that should prompt again prompt(); // db2 has a passphrase lock credentials - it'll work without U/I db2.unlock("wrong passphrase"); // pw=two, cred=three AutoCredentials pwCred2(alloc); pwCred2 += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), new(alloc) ListElement(passphrase)); // pwCred2 = (OLD: two) ss.authenticateDb(db2, CSSM_DB_ACCESS_WRITE, &pwCred2); // set it db2.unlock(); ss.lock(db2); // now change db2's passphrase ss.lock(db2); pwCred2 += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK, new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), new(alloc) ListElement(badPassphrase)); // pwCred2 = (OLD: two, NEW: three) db2.changePassphrase(&pwCred2); // passphrase = three, cred = (OLD: two) // encode and re-decode to make sure new data is there CssmData blob2; ss.encodeDb(db2, blob2); DbHandle db2a = ss.decodeDb(db2.dbId, &pwCred, blob2); // db2a cred = (OLD: two, NEW: three) // now, the *old* cred won't work anymore db2.unlock("old passphrase accepted"); // back to the old credentials, which *do* have the (old bad, now good) passphrase ss.lock(db2a); ss.unlock(db2a); detail("New passphrase accepted"); // clear the credentials (this will prompt; cancel it) ss.authenticateDb(db2, CSSM_DB_ACCESS_WRITE, NULL); prompt("cancel"); db2.unlock("null credential accepted"); prompt(); // fell-swoop from-to change password operation StringData newPassphrase("hollerith"); AutoCredentials pwCred3(alloc); pwCred3 += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK, new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), new(alloc) ListElement(newPassphrase)); pwCred3 += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), new(alloc) ListElement(passphrase)); db2.changePassphrase(&pwCred3, "accepting original (unchanged) passphrase"); AutoCredentials pwCred4(alloc); pwCred4 += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK, new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), new(alloc) ListElement(newPassphrase)); pwCred4 += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), new(alloc) ListElement(badPassphrase)); db2.changePassphrase(&pwCred4); // final status check AutoCredentials pwCred5(alloc); pwCred5 += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), new(alloc) ListElement(newPassphrase)); ss.authenticateDb(db2, CSSM_DB_ACCESS_WRITE, &pwCred5); db2.unlock(); detail("Final passphrase change verified"); }
void mkOCDB(const Bool_t toGRID=kFALSE, const Bool_t debug=kFALSE) { // This script reads PVBAR-EMC calibration object from OCDB raw://, // then reads corrections to gains O(1) from local://OCDB_corr // and create the new OCDB object with the new gains as a product of old gains // and gain corrections. // The new calibration object is written either to local://OCDB_new // -- // Gain corrections were found by equalizing the mean cell energy // from the reconstructed data LHC10h by B.Polishchuk // -- // Yuri Kharlov. 7-Feb-2011 TH1F *hGainOrigM1 = new TH1F("hGainOrigM1","hGainM1OrigM1",1000,0.,0.01); TH1F *hGainOrigM2 = new TH1F("hGainOrigM2","hGainM1OrigM2",1000,0.,0.01); TH1F *hGainOrigM3 = new TH1F("hGainOrigM3","hGainM1OrigM3",1000,0.,0.01); TH1F *hGainOrigM4 = new TH1F("hGainOrigM4","hGainM1OrigM4",1000,0.,0.01); TH1F *hGainOrigM5 = new TH1F("hGainOrigM5","hGainM1OrigM5",1000,0.,0.01); TH2F *hOrigNewM1 = new TH2F("hOrigNewM1","hOrigNewM1",100,0.,0.01,100,0.,0.01); TH2F *hOrigNewM2 = new TH2F("hOrigNewM2","hOrigNewM2",100,0.,0.01,100,0.,0.01); TH2F *hOrigNewM3 = new TH2F("hOrigNewM3","hOrigNewM3",100,0.,0.01,100,0.,0.01); TH2F *hOrigNewM4 = new TH2F("hOrigNewM4","hOrigNewM4",100,0.,0.01,100,0.,0.01); TH2F *hOrigNewM5 = new TH2F("hOrigNewM5","hOrigNewM5",100,0.,0.01,100,0.,0.01); TH1F *hGainNewM1 = new TH1F("hGainNewM1","hGainM1NewM1",1000,0.,0.01); TH1F *hGainNewM2 = new TH1F("hGainNewM2","hGainM1NewM2",1000,0.,0.01); TH1F *hGainNewM3 = new TH1F("hGainNewM3","hGainM1NewM3",1000,0.,0.01); TH1F *hGainNewM4 = new TH1F("hGainNewM4","hGainM1NewM4",1000,0.,0.01); TH1F *hGainNewM5 = new TH1F("hGainNewM5","hGainM1NewM5",1000,0.,0.01); IlcCDBManager::Instance()->SetDefaultStorage("raw://"); IlcCDBManager::Instance()->SetRun(114783); IlcPVBARCalibData db1(114783); IlcCDBManager::Instance()->SetDefaultStorage("local://OCDB_corr"); IlcCDBManager::Instance()->SetSpecificStorage("PVBAR/Calib/EmcGainPedestals", "local://OCDB_corr"); IlcCDBManager::Instance()->SetRun(114783); IlcPVBARCalibData db2(114783); for(Int_t module=0; module<5; module++) { for(Int_t ix=0; ix<64; ix++) { for(Int_t iz=0; iz<56; iz++) { Float_t cc_i = db1.GetADCchannelEmc(module+1,iz+1,ix+1); Float_t corr = db2.GetADCchannelEmc(module+1,iz+1,ix+1); if (module <= 2) corr *= 0.135/0.1223; if (module == 0) { hGainOrigM1->Fill(cc_i); hGainNewM1 ->Fill(cc_i*corr); hOrigNewM1 ->Fill(cc_i,cc_i*corr); } else if (module == 1) { hGainOrigM2->Fill(cc_i); hGainNewM2 ->Fill(cc_i*corr); hOrigNewM2 ->Fill(cc_i,cc_i*corr); } else if (module == 2) { hGainOrigM3->Fill(cc_i); hGainNewM3 ->Fill(cc_i*corr); hOrigNewM3 ->Fill(cc_i,cc_i*corr); } else if (module == 3) { hGainOrigM4->Fill(cc_i); hGainNewM4 ->Fill(cc_i*corr); hOrigNewM4 ->Fill(cc_i,cc_i*corr); } else if (module == 4) { hGainOrigM5->Fill(cc_i); hGainNewM5 ->Fill(cc_i*corr); hOrigNewM5 ->Fill(cc_i,cc_i*corr); } db1.SetADCchannelEmc(module+1,iz+1,ix+1,cc_i*corr); if (debug) { if (TMath::Abs(corr-1.)>0.01) printf("CC for mod%d x%d z%d set to %f (orig %f, corr %f)\n", module+1,ix+1,iz+1, db1.GetADCchannelEmc(module+1,iz+1,ix+1), cc_i,corr); } } } } //Writing new calibration coefficients (CCs) to OCDB IlcCDBManager* cdb = IlcCDBManager::Instance(); if (toGRID) cdb->SetDefaultStorage("alien://Folder=/ilc/cern.ch/user/k/kharlov/RAW/2010/OCDB"); else cdb->SetDefaultStorage("local://OCDB_new"); IlcCDBMetaData *md= new IlcCDBMetaData(); md->SetResponsible("Yuri Kharlov / Boris Polishchuk"); md->SetComment("PVBAR gains calculated from mean cell energy equalization. All scaled to shift pi0 to 135 MeV. HL/LG ratio is calculated from LED runs offline. The pi0 width is 5-7 MeV"); IlcCDBId id("PVBAR/Calib/EmcGainPedestals",114783,IlcCDBRunRange::Infinity()); // cdb->Put(&db1,id, md); db1.WriteEmc(136833,IlcCDBRunRange::Infinity(),md); TFile *gainHisto = new TFile("gainHisto.root","recreate"); hGainOrigM1->Write(); hGainOrigM2->Write(); hGainOrigM3->Write(); hGainOrigM4->Write(); hGainOrigM5->Write(); hGainNewM1->Write(); hGainNewM2->Write(); hGainNewM3->Write(); hGainNewM4->Write(); hGainNewM5->Write(); hOrigNewM1->Write(); hOrigNewM2->Write(); hOrigNewM3->Write(); hOrigNewM4->Write(); hOrigNewM5->Write(); gainHisto->Close(); }
int main(){ chdir(QUERY_DATA_PATH); EnvDB *env = new EnvDB(); env->open(); BDBOpe db1(env->getEnv(), DB1); BDBOpe db2(env->getEnv(), DB2); BDBOpe db3(env->getEnv(), DB3); BDBOpe db4(env->getEnv(), DB4); BDBOpe db5(env->getEnv(), DB5); BDBOpe db6(env->getEnv(), DB6); BDBOpe db7(env->getEnv(), DB7); BDBOpe db8(env->getEnv(), DB8); BDBOpe db9(env->getEnv(), DB9); BDBOpe db10(env->getEnv(), DB10); BDBOpe db11(env->getEnv(), DB11); BDBOpe db12(env->getEnv(), DB12); BDBOpe db13(env->getEnv(), DB13); BDBOpe db14(env->getEnv(), DB14); BDBOpe db15(env->getEnv(), DB15); BDBOpe db16(env->getEnv(), DB16); Operator *o1, *o2, *o3, *o4, *o5, *o6, *o7, *o8, *o9, *o10; Operator *o11, *o12, *o13, *o14, *o15, *o16, *o17, *o18, *o19, *o20; Operator *o21, *o22, *o23, *o24, *o25, *o26, *o27, *o28, *o29, *o30; Operator *o31, *o32; db1.open(); db2.open(); db3.open(); db4.open(); db5.open(); db6.open(); db7.open(); db8.open(); db9.open(); db10.open(); db11.open(); db12.open(); db13.open(); db14.open(); db15.open(); db16.open(); TABLE_REC tableRec; tableRec.tableID = DB_tableID; tableRec.attriNum = DB_attriNum; ATTRIBUTE_REC attriRec[tableRec.attriNum]; AttributeManager AM(env->getEnv()); AM.getForTableID(tableRec, attriRec); OPERATION_NODE op1; op1.tableID = 16; op1.attributeID = 1; OPERATION_NODE op2; op2.tableID = 16; op2.attributeID = 4; o1 = new ScanDSM(&db1, &attriRec[0], 1); o2 = new ScanDSM(&db2, &attriRec[1], 1); o3 = new ScanDSM(&db3, &attriRec[2], 1); o4 = new ScanDSM(&db4, &attriRec[3], 1); o5 = new ScanDSM(&db5, &attriRec[4], 1); o6 = new ScanDSM(&db6, &attriRec[5], 1); o7 = new ScanDSM(&db7, &attriRec[6], 1); o8 = new ScanDSM(&db8, &attriRec[7], 1); o9 = new ScanDSM(&db9, &attriRec[8], 1); o10 = new ScanDSM(&db10, &attriRec[9], 1); o11 = new ScanDSM(&db11, &attriRec[10], 1); o12 = new ScanDSM(&db12, &attriRec[11], 1); o13 = new ScanDSM(&db13, &attriRec[12], 1); o14 = new ScanDSM(&db14, &attriRec[13], 1); o15 = new ScanDSM(&db15, &attriRec[14], 1); o16 = new ScanDSM(&db16, &attriRec[15], 1); /* o17 = new ScanFromJI(o2, o1, &op1); o18 = new ScanFromJI(o3, o17, &op1); o19 = new ScanFromJI(o4, o18, &op1); o20 = new ScanFromJI(o5, o19, &op1); o21 = new ScanFromJI(o6, o20, &op1); o22 = new ScanFromJI(o7, o21, &op1); o23 = new ScanFromJI(o8, o22, &op1); o24 = new ScanFromJI(o9, o23, &op1); o25 = new ScanFromJI(o10, o24, &op1); o26 = new ScanFromJI(o11, o25, &op1); o27 = new ScanFromJI(o12, o26, &op1); o28 = new ScanFromJI(o13, o27, &op1); o29 = new ScanFromJI(o14, o28, &op1); o30 = new ScanFromJI(o15, o29, &op1); o31 = new ScanFromJI(o16, o30, &op1); */ o17 = new OutPut(TIME_OUT); o18 = new OutPut(TIME_OUT); o19 = new OutPut(TIME_OUT); o20 = new OutPut(TIME_OUT); o21 = new OutPut(TIME_OUT); o22 = new OutPut(TIME_OUT); o23 = new OutPut(TIME_OUT); o24 = new OutPut(TIME_OUT); o25 = new OutPut(TIME_OUT); o26 = new OutPut(TIME_OUT); o27 = new OutPut(TIME_OUT); o28 = new OutPut(TIME_OUT); o29 = new OutPut(TIME_OUT); o30 = new OutPut(TIME_OUT); o31 = new OutPut(TIME_OUT); o32 = new OutPut(TIME_OUT); o17->setPreOperator(o1); o17->init(env->getEnv()); o17->exec(); o18->setPreOperator(o2); o18->init(env->getEnv()); o18->exec(); o19->setPreOperator(o3); o19->init(env->getEnv()); o19->exec(); o20->setPreOperator(o4); o20->init(env->getEnv()); o20->exec(); o21->setPreOperator(o5); o21->init(env->getEnv()); o21->exec(); o22->setPreOperator(o6); o22->init(env->getEnv()); o22->exec(); o23->setPreOperator(o7); o23->init(env->getEnv()); o23->exec(); o24->setPreOperator(o8); o24->init(env->getEnv()); o24->exec(); o25->setPreOperator(o9); o25->init(env->getEnv()); o25->exec(); o26->setPreOperator(o10); o26->init(env->getEnv()); o26->exec(); o27->setPreOperator(o11); o27->init(env->getEnv()); o27->exec(); o28->setPreOperator(o12); o28->init(env->getEnv()); o28->exec(); o29->setPreOperator(o13); o29->init(env->getEnv()); o29->exec(); o30->setPreOperator(o14); o30->init(env->getEnv()); o30->exec(); o31->setPreOperator(o15); o31->init(env->getEnv()); o31->exec(); o32->setPreOperator(o16); o32->init(env->getEnv()); o32->exec(); }
// Compute the normal at a specific point in the patch. // The s and t values vary between 0 and 1. QVector3D QGLBezierPatch::normal(qreal s, qreal t) const { qreal a[4]; qreal b[4]; qreal tx, ty, tz; qreal sx, sy, sz; // Compute the derivative of the surface in t. a[0] = b0(s); a[1] = b1(s); a[2] = b2(s); a[3] = b3(s); b[0] = db0(t); b[1] = db1(t); b[2] = db2(t); b[3] = db3(t); tx = 0.0f; ty = 0.0f; tz = 0.0f; for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { tx += a[i] * points[j * 4 + i].x() * b[j]; ty += a[i] * points[j * 4 + i].y() * b[j]; tz += a[i] * points[j * 4 + i].z() * b[j]; } } // Compute the derivative of the surface in s. a[0] = db0(s); a[1] = db1(s); a[2] = db2(s); a[3] = db3(s); b[0] = b0(t); b[1] = b1(t); b[2] = b2(t); b[3] = b3(t); sx = 0.0f; sy = 0.0f; sz = 0.0f; for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { sx += a[i] * points[j * 4 + i].x() * b[j]; sy += a[i] * points[j * 4 + i].y() * b[j]; sz += a[i] * points[j * 4 + i].z() * b[j]; } } // The normal is the cross-product of the two derivatives, // normalized to a unit vector. QVector3D n = QVector3D::normal(QVector3D(sx, sy, sz), QVector3D(tx, ty, tz)); if (n.isNull()) { // A zero normal may occur if one of the patch edges is zero-length. // We correct for this by substituting an overall patch normal that // we compute from two of the sides that are not zero in length. QVector3D sides[4]; QVector3D vectors[2]; sides[0] = points[3] - points[0]; sides[1] = points[15] - points[3]; sides[2] = points[12] - points[15]; sides[3] = points[0] - points[12]; int i = 0; int j = 0; vectors[0] = QVector3D(1.0f, 0.0f, 0.0f); vectors[1] = QVector3D(0.0f, 1.0f, 0.0f); while (i < 2 && j < 4) { if (sides[j].isNull()) ++j; else vectors[i++] = sides[j++]; } n = QVector3D::normal(vectors[0], vectors[1]); } return n; }