PcbXML::PcbXML( const QDomElement & pcbDocument ) { // TODO: need some execption handling for bad elements missing attrs, etc. m_svg = new SVGDomDocument(); m_svgroot = m_svg->documentElement(); // FIXME: what happens when there is no mark - should be 0 m_markx = pcbDocument.attribute("MX").toInt(); m_marky = pcbDocument.attribute("MY").toInt(); m_units = pcbDocument.attribute("units"); m_minx = m_markx; m_miny = m_marky; m_maxx = m_markx; m_maxy = m_marky; m_pinCount = 0; m_padCount = 0; m_silkscreen = m_svg->createGroup("silkscreen"); m_copper = m_svg->createGroup("copper0"); m_keepout = m_svg->createGroup("keepout"); m_mask = m_svg->createGroup("soldermask"); m_outline = m_svg->createGroup("outline"); QDomNodeList tagList = pcbDocument.childNodes(); //TODO: eventually need to support recursing into the tree here //TODO: support footprints with multiple root elements (module style) for(uint i = 0; i < tagList.length(); i++){ drawNode(tagList.item(i)); } m_svg->setHeight(m_maxy-m_miny, m_units); m_svg->setWidth(m_maxx-m_minx, m_units); m_svg->setViewBox(0,0,m_maxx-m_minx,m_maxy-m_miny); shiftCoordinates(); m_svgFile = QDir::tempPath () + "/footprint.svg"; DebugDialog::debug(QString("temp path %1").arg(QDir::tempPath () + "/test.svg" ) ); m_svg->save(m_svgFile); }
//------------------------------ void MolState::align() { // Shift center of mass to the origin: shiftCoordinates( getCenterOfMass() ); // Aligh moment of inertia principal axes: KMatrix MOI_tensor(3,3), MOI_eigenValues(3,1), MOI_eigenVectors(3,3); MOI_tensor = getMomentOfInertiaTensor(); //MOI_tensor.Print("Moment of inertia tensor"); MOI_eigenVectors=MOI_tensor.Herm_Diag(MOI_eigenValues, true); // true=>eigen vals in the descending order; eigen vectors in ROWS. // MOI_eigenVectors.Print("MOI eigen vectors"); // MOI_eigenValues.Print("MOI eigen values"); // compute the determinant of MOI matrix: double det_tmp = MOI_eigenVectors.Determinant(); // if determinant is = 1 than it is a proper rotation; // if it is = -1 than it is rotation+reflection (switch from left handed to the right handed coord.system); swap x&y axes: if (det_tmp < 0) MOI_eigenVectors.SwapRows(0,1); transformCoordinates(MOI_eigenVectors); // rotate coordinates using matrix of the MOI eigen vectors std::cout << "Coordinate axes were aligned with MOI principal axes; center mass was shifted to the origin.\n"; }
//------------------------------ bool MolState::Read() { int i,j,k,l; char tmpCh; std::string tmp_str, tmp_atomName; std::istringstream tmp_iStr; Atom tmp_atom; //------------ Read IP (if provided) ---------------------------------- if ( xmlF.CheckSubNode("ip") ) { xmlF.node("ip"); energy = xmlF.getDoubleValue(); xmlF.stepBack(); } //------------ Read the Geometry -------------------------------------- xmlF.node("geometry"); int tmp_nAtoms, tmp_nNormMds; tmp_nAtoms=xmlF.getIntValue("number_of_atoms"); std::string units; units=xmlF.value("units"); ifLinear= xmlF.getBoolValue("linear"); if (ifLinear) tmp_nNormMds = (3*tmp_nAtoms - 5); else tmp_nNormMds = (3*tmp_nAtoms - 6); tmp_iStr.str(xmlF.value("text")); tmp_iStr.clear(); atoms.clear(); for (i=0; i<tmp_nAtoms; i++) { tmp_atomName=""; tmpCh=' '; while ( !ifLetterOrNumber(tmpCh) and !(tmp_iStr.fail()) ) tmp_iStr.get(tmpCh); if (tmp_iStr.fail()) { std::cout << "\nError: less then "<< tmp_nAtoms <<" atoms found or the format error, \"text\"-s line nuumber "<<i+1<<"\n"; xmlF.exitOnFormatError(true); } do { tmp_atomName+=tmpCh; tmp_iStr.get( tmpCh ); } while( ifLetterOrNumber(tmpCh) ); tmp_atom.Name() = tmp_atomName; for (k=0; k<CARTDIM; k++) { tmp_iStr >> tmp_atom.Coord(k); if (units=="au") tmp_atom.Coord(k)*=AU2ANGSTROM; } if (tmp_iStr.fail()) { std::cout << "\nError: less then "<< tmp_nAtoms <<" atoms found or the format error in the atomic coordinates,\n" << " \"text\"-s line number "<<i+1<<"\n"; xmlF.exitOnFormatError(true); } atoms.push_back(tmp_atom); } //------------ Convert atomic names to masses -------------------------- for (i=0; i<NAtoms(); i++) { tmp_iStr.str( amuF.reset().node("masses").node( getAtom(i).Name().c_str() ).value() ); tmp_iStr.clear(); tmp_iStr >> getAtom(i).Mass(); amuF.exitOnFormatError(tmp_iStr.fail()); } //------------ Read Normal Modes --------------------------------------- NormalMode tmp_normMode(NAtoms(),0); // one temp. norm mode normModes.clear(); xmlF.stepBack(); xmlF.node("normal_modes"); tmp_iStr.str(xmlF.value("text")); tmp_iStr.clear(); for (i=0; i < tmp_nNormMds; i++) normModes.push_back( tmp_normMode ); int nModesPerLine=3; // three number of vib. modes per Line int nLines; nLines = tmp_nNormMds / nModesPerLine; if ( tmp_nNormMds % nModesPerLine != 0) nLines++; for (k = 0; k < nLines; k++) // number of blocks with 3 norm.modes. ("lines") { int current_nModesPerLine = nModesPerLine; // for the last entree, nModesPerString may differ from 3 if (nLines - 1 == k) if ( tmp_nNormMds % nModesPerLine != 0 ) current_nModesPerLine = tmp_nNormMds % nModesPerLine; for (i=0; i < NAtoms(); i++) for (j=0; j < current_nModesPerLine; j++) for (l=0; l < CARTDIM; l++) { tmp_iStr >> normModes[k*nModesPerLine+j].getDisplacement()[i*CARTDIM+l]; if (tmp_iStr.fail()) { std::cout << "\nError: less normal modes found than expected or the format error\n"; xmlF.exitOnFormatError(true); } } } //------------ Read Frequencies ---------------------------------------- xmlF.stepBack(); xmlF.node("frequencies"); tmp_iStr.str(xmlF.value("text")); tmp_iStr.clear(); for (i=0; i < tmp_nNormMds; i++) { tmp_iStr >> getNormMode(i).getFreq(); if (tmp_iStr.fail()) { std::cout << "\nError: format error at frequency #"<<i<< " or less than " << tmp_nNormMds <<" frequencies found\n"; xmlF.exitOnFormatError(true); } if (getNormMode(i).getFreq()<=0) { std::cout <<"\nError. The frequency ["<<getNormMode(i).getFreq() <<"] is negative\n"; xmlF.exitOnFormatError(true); } } // Now MolState is in a good shape, and some transformations can be performed //------------ 1. Un-mass-weight normal modes---------------------------- xmlF.stepBack(); xmlF.node("normal_modes"); bool if_massweighted; if_massweighted=xmlF.getBoolValue("if_mass_weighted"); //------------ 1. mass un-weight normal modes, if needed (QChem-->ACES format; )---------------- // qchem if_massweighted="true"; aces if_massweighted="false"; reduced_masses.Adjust(NNormModes(),1); reduced_masses.Set(1); if (if_massweighted) { // Read atomic names from "...->normal_modes->atoms" std::vector<Atom> normalModeAtoms; tmp_iStr.str(xmlF.value("atoms")); tmp_iStr.clear(); normalModeAtoms.clear(); for (i=0; i<NAtoms(); i++) { tmp_atomName=""; tmpCh=' '; while ( !ifLetterOrNumber(tmpCh) and !(tmp_iStr.fail()) ) tmp_iStr.get(tmpCh); xmlF.exitOnFormatError(tmp_iStr.fail()); do { tmp_atomName+=tmpCh; tmp_iStr.get( tmpCh ); } while( ifLetterOrNumber(tmpCh) ); tmp_atom.Name() = tmp_atomName; normalModeAtoms.push_back(tmp_atom); } // Get masses for each atomic name: for (i=0; i<NAtoms(); i++) { tmp_iStr.str( amuF.reset().node("masses").node( normalModeAtoms[i].Name().c_str() ).value() ); tmp_iStr.clear(); tmp_iStr >> normalModeAtoms[i].Mass(); amuF.exitOnFormatError(tmp_iStr.fail()); } // Mass-un-weight normal modes: for (int nm=0; nm<NNormModes(); nm++) for (int a=0; a<NAtoms(); a++) for (int i=0; i<CARTDIM; i++ ) getNormMode(nm).getDisplacement().Elem1(a*CARTDIM+i) *= sqrt(normalModeAtoms[a].Mass()); // normolize each normal mode (/sqrt(norm) which is also /sqrt(reduced mass)): // KMatrix reduced_masses(NNormModes(),1); for (int nm=0; nm<NNormModes(); nm++) { reduced_masses[nm] = 0; for (int a=0; a<NAtoms(); a++) for (int i=0; i<CARTDIM; i++ ) reduced_masses[nm]+= getNormMode(nm).getDisplacement().Elem1(a*CARTDIM+i) * getNormMode(nm).getDisplacement().Elem1(a*CARTDIM+i); } // reduced_masses.Print("Reduced masses:"); // Normalize: for (int nm=0; nm<NNormModes(); nm++) for (int a=0; a<NAtoms(); a++) for (int i=0; i<CARTDIM; i++ ) getNormMode(nm).getDisplacement().Elem1(a*CARTDIM+i)/=sqrt(reduced_masses[nm]); } xmlF.stepBack(); //------------ 2. Align geometry if requested ---------------------------- if_aligned_manually=false; double man_rot_x, man_rot_y, man_rot_z; Vector3D man_shift; if ( xmlF.CheckSubNode("manual_coordinates_transformation") ) { xmlF.node("manual_coordinates_transformation"); man_rot_x=xmlF.getDoubleValue("rotate_around_x"); man_rot_y=xmlF.getDoubleValue("rotate_around_y"); man_rot_z=xmlF.getDoubleValue("rotate_around_z"); man_shift.getCoord(0)=-xmlF.getDoubleValue("shift_along_x"); man_shift.getCoord(1)=-xmlF.getDoubleValue("shift_along_y"); man_shift.getCoord(2)=-xmlF.getDoubleValue("shift_along_z"); std::cout << "Molecular structure and normal modes of this electronic state\nwill be transformed as requested in the input.\n"; shiftCoordinates(man_shift); rotate(man_rot_x*PI,man_rot_y*PI,man_rot_z*PI); applyCoordinateThreshold(COORDINATE_THRESHOLD); if_aligned_manually=true; xmlF.stepBack(); } //------------ 3. Reorder normal modes if requested -------------------- if ( xmlF.CheckSubNode("manual_normal_modes_reordering") ) { xmlF.node("manual_normal_modes_reordering"); if_nm_reordered_manually=false; normModesOrder.clear(); std::cout << "New normal modes order was requested:\n" << xmlF.value("new_order") <<"\n"; tmp_iStr.str(xmlF.value("new_order")); int tmpInt; for (int nm=0; nm < NNormModes(); nm++) { tmp_iStr >> tmpInt; //input error check: if (tmp_iStr.fail()) { std::cout << "\nFormat error: non numeric symbol or less entries then the number of normal modes\n\n"; xmlF.exitOnFormatError(true); } if ( (tmpInt<0) or (tmpInt>=NNormModes()) ) { std::cout << "\nError: normal mode number ["<< tmpInt<<"] is out of range [0.."<<NNormModes()-1<<"].\n\n"; xmlF.exitOnFormatError(true); } normModesOrder.push_back(tmpInt); } // check if there are duplicates in the list: std::vector<int> tmpIntVector, tmpIntVector2; tmpIntVector = normModesOrder; std::sort( tmpIntVector.begin(), tmpIntVector.end() ); tmpIntVector2 = tmpIntVector; std::vector<int>::const_iterator intVec_iter; intVec_iter= unique( tmpIntVector.begin(), tmpIntVector.end() ); if (intVec_iter != tmpIntVector.end()) { std::cout << "\nFormat error: there are non unique entries. Check the sorted list:\n"; for (std::vector<int>::const_iterator tmp_iter=tmpIntVector2.begin(); tmp_iter!=tmpIntVector2.end(); tmp_iter++) std::cout << ' ' << *tmp_iter; std::cout<<'\n'; xmlF.exitOnFormatError(true); } // backup normal modes std::vector<NormalMode> oldNormModes; oldNormModes.clear(); for (int nm=0; nm < NNormModes(); nm++) { tmp_normMode = getNormMode(nm); oldNormModes.push_back( tmp_normMode ); } // copy normal modes using new order for (int nm=0; nm < NNormModes(); nm++) getNormMode(nm) = oldNormModes[ normModesOrder[nm] ]; std::cout << "Normal modes were reordered accordingly.\n"; if_nm_reordered_manually=true; xmlF.stepBack(); }