void run() { AVThread *avt = demux_thread->videoThread(); avt->packetQueue()->clear(); // clear here if (pts <= 0) { demux_thread->demuxer->seek(qint64(-pts*1000.0) - 500LL); QVector<qreal> ts; qreal t = -1.0; while (t < -pts) { demux_thread->demuxer->readFrame(); if (demux_thread->demuxer->stream() != demux_thread->demuxer->videoStream()) continue; t = demux_thread->demuxer->packet().pts; ts.push_back(t); } const qreal t0 = ts.back(); ts.pop_back(); const qreal dt = t0 - ts.back(); pts = ts.back(); // FIXME: sometimes can not seek to the previous pts, the result pts is always current pts, so let the target pts a little earlier pts -= dt/2.0; } qDebug("step backward: %lld, %f", qint64(pts*1000.0), pts); demux_thread->video_thread->setDropFrameOnSeek(false); demux_thread->seekInternal(qint64(pts*1000.0), AccurateSeek); }
/** Returns a list of points on the bandwidth graph based on the supplied set * of rsdht or alldht values. */ void RSGraphWidget::pointsFromData(const std::vector<QPointF>& values,QVector<QPointF>& points) { points.clear(); int x = _rec.width(); int y = _rec.height(); float time_step = 1.0f ; // number of seconds per pixel /* Translate all data points to points on the graph frame */ // take 0 as the origin, otherwise the different curves are not aligned properly float last = 0;//values.back().x(); //std::cerr << "Got " << values.size() << " values for index 0" << std::endl; float last_px = SCALE_WIDTH ; float last_py = 0.0f ; for (uint i = 0; i < values.size(); ++i) { //std::cerr << "Value: (" << values[i].x() << " , " << values[i].y() << ")" << std::endl; // compute point in pixels qreal px = x - (values[i].x()-last)*_time_scale ; qreal py = y - valueToPixels(values[i].y()) ; if(px >= SCALE_WIDTH && last_px < SCALE_WIDTH) { float alpha = (SCALE_WIDTH - last_px)/(px - last_px) ; float ipx = SCALE_WIDTH ; float ipy = (1-alpha)*last_py + alpha*py ; points << QPointF(ipx,y) ; points << QPointF(ipx,ipy) ; } else if(i==0) points << QPointF(px,y) ; last_px = px ; last_py = py ; if(px < SCALE_WIDTH) continue ; _maxValue = std::max(_maxValue,values[i].y()) ; // remove midle point when 3 consecutive points have the same value. if(points.size() > 1 && points[points.size()-2].y() == points.back().y() && points.back().y() == py) points.pop_back() ; points << QPointF(px,py) ; if(i==values.size()-1) points << QPointF(px,y) ; } }
QVector<double> DataContainer::combineXVectors(const QVector<double> x1, const QVector<double> x2) { //union of xdata // QVector<double> ret; // ret.resize(std::max(x1.size(), x2.size())); // int ind1 = 0; // int ind2 = 0; // while (ind1 < x1.size() || ind2 < x2.size()) { // if (ind1 == x1.size()) { // ret.push_back(x2[ind2++]); // } else if (ind2 == x2.size()) { // ret.push_back(x1[ind1++]); // } else { // if (x1[ind1] < x2[ind2]) // ret.push_back(x1[ind1++]); // else // ret.push_back(x2[ind2++]); // } // } //TODO - make algorithm more optimal if (x1.isEmpty() | x2.isEmpty()) return QVector<double>(); if (x1.size() == x2.size()) { if (x1 == x2) return x1; } QVector<double> retBuf = x1; retBuf += x2; qSort(retBuf.begin(), retBuf.end()); // double xlow = std::max(x1[0], x2[0]); // double xhigh = std::min(x1[x1.size() - 1], x2[x2.size() - 1]); double xlow = std::max(x1[0], x2[0]); double xhigh = std::min(x1.back(), x2.back()); QVector<double> ret; ret.reserve(std::max(x1.size(), x2.size()) / 2); foreach (double x, retBuf) { if (x >= xlow && x <= xhigh) { // if (ret.size() == 0 || x != ret[ret.size() - 1]) //avoiding equal numbers // ret.push_back(x); if (ret.size() == 0 || x != ret.back()) //avoiding equal numbers ret.push_back(x); } } return ret; }
void appendMessage(const QString &text, OutputFormat format) final { const bool isTrace = (format == StdErrFormat || format == StdErrFormatSameLine) && (text.startsWith("Traceback (most recent call last):") || text.startsWith("\nTraceback (most recent call last):")); if (!isTrace) { OutputFormatter::appendMessage(text, format); return; } const QTextCharFormat frm = charFormat(format); const Core::Id id(PythonErrorTaskCategory); QVector<Task> tasks; const QStringList lines = text.split('\n'); unsigned taskId = unsigned(lines.size()); for (const QString &line : lines) { const QRegularExpressionMatch match = filePattern.match(line); if (match.hasMatch()) { QTextCursor tc = plainTextEdit()->textCursor(); tc.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); tc.insertText('\n' + match.captured(1)); tc.insertText(match.captured(2), linkFormat(frm, match.captured(2))); const auto fileName = FileName::fromString(match.captured(3)); const int lineNumber = match.capturedRef(4).toInt(); Task task(Task::Warning, QString(), fileName, lineNumber, id); task.taskId = --taskId; tasks.append(task); } else { if (!tasks.isEmpty()) { Task &task = tasks.back(); if (!task.description.isEmpty()) task.description += ' '; task.description += line.trimmed(); } OutputFormatter::appendMessage('\n' + line, format); } } if (!tasks.isEmpty()) { tasks.back().type = Task::Error; for (auto rit = tasks.crbegin(), rend = tasks.crend(); rit != rend; ++rit) TaskHub::addTask(*rit); } }
void CorrespondenceSearch::applyCorrespondence(const PartsCorrespondence & correspondence) { QVector<ParticleMesh*> input; input << sA << sB; QVector<Particles> particles; particles << sA->particles << sB->particles; for( auto & pairing : correspondence ) { PartCorresponder::correspondSegments( pairing, input, particles ); // DEBUG: if( true ) { auto ls = new starlab::LineSegments(3); auto boxA = sA->segmentBoundingBox( input[0]->property["segments"].value<Segments>()[pairing.first] ); auto boxB = sB->segmentBoundingBox( input[1]->property["segments"].value<Segments>()[pairing.second] ); ls->addLine( Vector3( boxA.center() ), Vector3(boxB.center() + Vector3(1,0,0)), Qt::black ); debug << ls; } } // Assign back sA->particles = particles.front(); sB->particles = particles.back(); }
QVector<chatMes> sql::getHistoryChat(QMap<QString, QVariant> map) { QSqlQuery query(db); QVector<chatMes> mesVec; int userID = getFriendID(map["friendQQ"].toLongLong()) ; int friendID = getFriendID(map["meQQ"].toLongLong()); int offset = map[ "offset" ].toInt(); if ( !query.exec(sql_statement::historyChat_str(userID,friendID,offset) ) ) { qDebug()<<"getHistoryChat fail: "<<query.lastError().text(); return mesVec; } qDebug()<<sql_statement::historyChat_str(userID,friendID,offset); int size = query.size(); if (size==0) { return mesVec; } int i=0; while(query.next()) { chatMes mes; int fromID = query.value(0).toInt(); mes.fromAccount = QString::number(fromID+N); mes.content = query.value(1).toString(); mes.time=QDateTime::fromString(query.value(2).toString(),"yyyy-MM-dd hh:mm"); mes.type = query.value(3).toInt(); mesVec.push_back(mes); qDebug()<<" getHistoryChat"<<mesVec.count() <<mesVec.back().fromAccount<< " "<<mesVec.back().content; } return mesVec; }
void PartCorresponder::match1DGridChunk( QVector< QVector<SliceChunk> > sortedChunk, const QVector<ParticleMesh *> & input, QVector<Particles> & particles ) { QVector< QVector<SliceChunk> > readyChunkPairs; auto & sortedChunkFront = sortedChunk.front(); auto & sortedChunkBack = sortedChunk.back(); // Different number of chunks if( sortedChunkFront.size() != sortedChunkBack.size() ) { int targetSize = std::min( sortedChunkFront.size(), sortedChunkBack.size() ); if(targetSize == 1) { QVector<SliceChunk> chunkPairs; if( sortedChunkFront.size() == 1 ) chunkPairs.push_back( sortedChunkFront.front() ); else chunkPairs.push_back( mergeChunks( sortedChunkFront, input.front(), particles.front() ) ); if( sortedChunkBack.size() == 1) chunkPairs.push_back( sortedChunkBack.front() ); else chunkPairs.push_back( mergeChunks( sortedChunkBack, input.back(), particles.back() ) ); readyChunkPairs.push_back( chunkPairs ); } else { // For now we use basic matching.. later we should either split / merge for(auto v : distributeVectors(sortedChunkFront.size(), sortedChunkBack.size())) { QVector<SliceChunk> p; p << sortedChunkFront[v.first] << sortedChunkBack[v.second]; readyChunkPairs.push_back( p ); } } } else { // Same number of elements, simply match them up for(size_t i = 0; i < sortedChunk.front().size(); i++) { readyChunkPairs.push_back( QVector<SliceChunk>() << sortedChunkFront.at(i) << sortedChunkBack.at(i) ); } } // Match each pair of chunks for(auto & pairChunk : readyChunkPairs) matchChunk(pairChunk, input, particles); }
value_type *AddVariable(const char_type *varName, void *userData) { (void)varName; QVector<value_type> *vec = (QVector<value_type> *)userData; vec->push_back(0); return &vec->back(); }
void PaintWidget::waypointsChanged() { m_request.target = RoutingLogic::instance()->target(); QVector< UnsignedCoordinate > waypoints = RoutingLogic::instance()->waypoints(); if ( waypoints.size() > 0 && RoutingLogic::instance()->target() == waypoints.back() ) waypoints.pop_back(); m_request.waypoints = waypoints; update(); }
void Record::createWaveFormPic(Ffmpeg_t *ffmpeg, QString recortPath) { std::pair<std::vector<double>, std::vector<double> > dataWaveForm = ffmpeg->getSamplesForWaveformPlotting(recortPath + "/" + m_Name); QCustomPlot Plotter; Plotter.setBackground(QBrush(Qt::transparent) ); Plotter.xAxis->setVisible(false); Plotter.yAxis->setVisible(false); Plotter.axisRect()->setAutoMargins(QCP::msNone); Plotter.axisRect()->setMargins(QMargins(0, 5, 0, 5)); QCPGraph *Waveform = Plotter.addGraph(); Waveform->setPen(QPen(Qt::green) ); if (!Waveform) { qDebug("addGraph failed\n"); } QVector<double> Amplitudes(QVector<double>::fromStdVector(dataWaveForm.first) ); QVector<double> Time; double CurrentTime = 0; auto TimeSlotCount = Amplitudes.size(); for (int64_t i = 1; i < TimeSlotCount; i++) { Time.append(CurrentTime); CurrentTime += 0.5; } Waveform->setData(Time, Amplitudes); Plotter.xAxis->setRange(0, Time.back() ); Plotter.yAxis->setRange(SHRT_MIN, SHRT_MAX); QByteArray ByteArray; QBuffer Buffer(&ByteArray); Buffer.open(QBuffer::WriteOnly); uint32_t time = m_EndTime - m_StartTime; for (int i = 1; i < 10000; i*=10) { Plotter.toPixmap(time/(i), this->height()).save(&Buffer, "PNG", 0); //Plotter.saveJpg(recortPath + "/plot" + QString::number(m_Id) + QString::number(i) + ".jpg", time/(i), this->height()); QPixmap Pixmap; Pixmap.loadFromData(ByteArray, "PNG"); v_PixWaves.append(Pixmap); ByteArray.clear(); Buffer.reset(); } Buffer.close(); qDebug() << m_WavePic->margin(); // místo 2 podle toho jaký zoom m_WavePic->setPixmap(v_PixWaves[2]); }
void TaskSheet::executeGrowShrinkSheet(double t) { Structure::Sheet* structure_sheet = ((Structure::Sheet*)node()); QVector<Link*> edges = active->getEdges( property["edges"].value< QVector<int> >() ); /// Single edge case if ( property.contains("deltas") ) { Array2D_Vector3 cpts = property["orgCtrlPoints"].value<Array2D_Vector3>(); Array2D_Vector3 deltas = property["deltas"].value<Array2D_Vector3>(); // Grow sheet for(size_t u = 0; u < structure_sheet->surface.mNumUCtrlPoints; u++) for(size_t v = 0; v < structure_sheet->surface.mNumVCtrlPoints; v++) structure_sheet->surface.mCtrlPoint[u][v] = cpts[u][v] + (deltas[u][v] * t); } /// Two edges case if( property.contains("pathA") && property.contains("pathB") && property.contains("cpCoords") ) { QVector< GraphDistance::PathPointPair > pathA = property["pathA"].value< QVector< GraphDistance::PathPointPair > >(); QVector< GraphDistance::PathPointPair > pathB = property["pathB"].value< QVector< GraphDistance::PathPointPair > >(); if(pathA.size() == 0 || pathB.size() == 0) return; double dt = t; if(type == SHRINK) dt = 1 - t; double decodeT = qMin(1.0, dt * 2.0); int idxA = dt * (pathA.size() - 1); int idxB = dt * (pathB.size() - 1); // Move to next step Vector3 pointA = pathA[idxA].position(active); Vector3 pointB = pathB[idxB].position(active); Structure::Link *linkA = edges.front(), *linkB = edges.back(); if (type == GROW){ linkA = target->getEdge(linkA->property["correspond"].toInt()); linkB = target->getEdge(linkB->property["correspond"].toInt()); } Vector3d deltaA = linkA->property["delta"].value<Vector3d>() * dt; Vector3d deltaB = linkB->property["delta"].value<Vector3d>() * dt; Array1D_Vector3 decoded = Curve::decodeCurve(property["cpCoords"].value<CurveEncoding>(), pointA + deltaA, pointB + deltaB, decodeT); structure_sheet->setControlPoints( decoded ); } }
void checkVColour(QVector< QVector<Candy*> > board, int dimension) { QVector<Candy*> same; for (int j = 0; j < dimension; j++) { for (int i = 0; i < dimension; i++) { if (same.empty()) same.push_back(board[i][j]); else if (!same.empty()) { if (same.size() == 5) { same = checkXColour(board, same); for (int k = 0; k < 5; k++) same[k]->setCandy(0); same.clear(); same.push_back(board[i][j]); } else if (board[i][j]->getCol() == same.back()->getCol() + 1) { if (board[i][j]->getCandy() == same.back()->getCandy()) same.push_back(board[i][j]); else { same.clear(); same.push_back(board[i][j]); } } } } if (same.size() == 5) { for (int k = 0; k < 5; k++) same[k]->setCandy(0); } same.clear(); } }
void OsmAnd::RoutePlanner::addRouteSegmentToRoute( QVector< std::shared_ptr<RouteSegment> >& route, const std::shared_ptr<RouteSegment>& segment, bool reverse ) { if (segment->startPointIndex == segment->endPointIndex) return; if (route.size() > 0) { auto last = route.back(); if (last->road->id == segment->road->id) { if (combineTwoSegmentResult(segment, last, reverse)) return; } } route.push_back(segment); }
QVector<rpp::pp_macro*> computeGccStandardMacros(bool withStdCpp0x = true) { QVector<rpp::pp_macro*> ret; //Get standard macros from gcc KProcess proc; proc.setOutputChannelMode(KProcess::MergedChannels); // The output of the following gcc commands is several line in the format: // "#define MACRO [definition]", where definition may or may not be present. // Parsing each line sequentially, we can easily build the macro set. proc << "gcc"; if (withStdCpp0x) { // see also: https://bugs.kde.org/show_bug.cgi?id=298252 proc << "-std=c++0x"; } proc << "-xc++" << "-E" << "-dM" <<NULL_DEVICE; if (proc.execute(5000) == 0) { QString line; while (proc.canReadLine()) { QByteArray buff = proc.readLine(); if (!buff.isEmpty()) { line = buff; if (line.startsWith("#define ")) { line = line.right(line.length() - 8).trimmed(); int pos = line.indexOf(' '); ret.append(new rpp::pp_macro); rpp::pp_macro& macro(*ret.back()); if (pos != -1) { macro.name = IndexedString( line.left(pos) ); macro.setDefinitionText( line.right(line.length() - pos - 1).toUtf8() ); } else { macro.name = IndexedString( line ); } } } } } else if (withStdCpp0x) { // fallback to macro computation without -std=c++0x arg for old gcc versions return computeGccStandardMacros(false); } else { kDebug(9007) <<"Unable to read standard c++ macro definitions from gcc:" <<QString(proc.readAll()) ; } return ret; }
void TaskSheet::prepareGrowShrinkSheet() { Structure::Node * n = node(); QVector<Structure::Link*> edges = filterEdges(n, active->getEdges(n->id)); property["edges"].setValue( active->getEdgeIDs(edges) ); if (edges.size() == 1) { prepareSheetOneEdge( edges.front() ); } if (edges.size() == 2) { prepareSheetTwoEdges( edges.front(), edges.back() ); } }
uint32_t TimelineBar::processDraws(QVector<Marker> &markers, QVector<uint32_t> &draws, const rdcarray<DrawcallDescription> &curDraws) { uint32_t maxEID = 0; for(const DrawcallDescription &d : curDraws) { if(!d.children.isEmpty()) { markers.push_back(Marker()); Marker &m = markers.back(); m.name = d.name; m.eidStart = d.eventId; m.eidEnd = processDraws(m.children, m.draws, d.children); maxEID = qMax(maxEID, m.eidEnd); if(d.markerColor[3] > 0.0f) { m.color = QColor::fromRgb( qRgb(d.markerColor[0] * 255.0f, d.markerColor[1] * 255.0f, d.markerColor[2] * 255.0f)); } else { m.color = QColor(Qt::gray); } } else { if(!(d.flags & DrawFlags::SetMarker)) { m_Draws.push_back(d.eventId); draws.push_back(d.eventId); } } maxEID = qMax(maxEID, d.eventId); } return maxEID; }
void CollectionWindow::addToCollection(const QVector<QPair<int, int>>& additions) { for (const QPair<int,int>& add : additions) { auto currentQuantity = collectionTableModel_.getQuantity(add.first); collectionTableModel_.setQuantity(add.first, currentQuantity + add.second); } if (!additions.empty()) { int rowIndex = mtg::Collection::instance().getRowIndex(additions.back().first); if (rowIndex >= 0) { int columnIndex = ui_.collectionTbl_->horizontalHeader()->logicalIndexAt(0); QModelIndex sourceIndex = collectionTableModel_.sourceModel()->index(rowIndex, columnIndex); QModelIndex proxyIndex = collectionTableModel_.mapFromSource(sourceIndex); ui_.collectionTbl_->setCurrentIndex(proxyIndex); } } updateStatusBar(); }
void CollectionWindow::addToCollection(const QVector<int>& dataRowIndices) { for (const int dataRowIndex : dataRowIndices) { auto currentQuantity = collectionTableModel_.getQuantity(dataRowIndex); collectionTableModel_.setQuantity(dataRowIndex, currentQuantity + 1); } if (!dataRowIndices.empty()) { int rowIndex = mtg::Collection::instance().getRowIndex(dataRowIndices.back()); if (rowIndex >= 0) { int columnIndex = ui_.collectionTbl_->horizontalHeader()->logicalIndexAt(0); QModelIndex sourceIndex = collectionTableModel_.sourceModel()->index(rowIndex, columnIndex); QModelIndex proxyIndex = collectionTableModel_.mapFromSource(sourceIndex); ui_.collectionTbl_->setCurrentIndex(proxyIndex); } } updateStatusBar(); }
QVector<rpp::pp_macro*> computeGccStandardMacros() { QVector<rpp::pp_macro*> ret; //Get standard macros from gcc KProcess proc; proc.setOutputChannelMode(KProcess::MergedChannels); proc.setTextModeEnabled(true); // The output of the following gcc commands is several line in the format: // "#define MACRO [definition]", where definition may or may not be present. // Parsing each line sequentially, we can easily build the macro set. proc <<"gcc" <<"-xc++" <<"-E" <<"-dM" <<"/dev/null"; if (proc.execute(5000) == 0) { QString line; while (proc.canReadLine()) { QByteArray buff = proc.readLine(); if (!buff.isEmpty()) { line = buff; if (line.startsWith("#define ")) { line = line.right(line.length() - 8).trimmed(); int pos = line.indexOf(' '); ret.append(new rpp::pp_macro); rpp::pp_macro& macro(*ret.back()); if (pos != -1) { macro.name = IndexedString( line.left(pos) ); macro.setDefinitionText( line.right(line.length() - pos - 1).toUtf8() ); } else { macro.name = IndexedString( line ); } } } } } else { kDebug(9007) <<"Unable to read standard c++ macro definitions from gcc:" <<QString(proc.readAll()) ; } return ret; }
void TaskSheet::prepareCrossingSheet() { Structure::Node * n = node(); //QVector<Structure::Link*> edges = filterEdges(n, active->getEdges(n->id)); // For now, let us only use one edge: QVector<Structure::Link*> edges; edges.push_back( filterEdges(n, active->getEdges(n->id)).front() ); if (edges.size() == 1) { // Start and end Link * link = edges.front(); Vector3d start = link->positionOther(n->id); NodeCoord futureNodeCord = futureLinkCoord(link); Vector3d end = active->position(futureNodeCord.first,futureNodeCord.second); // Geodesic distances on the active graph excluding the running tasks QVector< GraphDistance::PathPointPair > path; QVector<QString> exclude = active->property["activeTasks"].value< QVector<QString> >(); GraphDistance gd( active, exclude ); gd.computeDistances( end, DIST_RESOLUTION ); gd.smoothPathCoordTo( start, path ); // Check if(path.size() < 2) { path.clear(); path.push_back(GraphDistance::PathPointPair( PathPoint(futureNodeCord.first, futureNodeCord.second))); } property["path"].setValue( GraphDistance::positionalPath(active, path) ); // Save links paths path.back() = GraphDistance::PathPointPair( PathPoint(futureNodeCord.first, futureNodeCord.second) ); link->setProperty("path", path); } property["edges"].setValue( active->getEdgeIDs(edges) ); }
RowStore RowStoreModel::cacheFromLiveNodes(LiveNodes const &livenodes) { if(LiveNodeModel *model = livenodes.model()) { if(RowStoreModel *modeldata = dynamic_cast<RowStoreModel *>(model)) return modeldata->row_store; QVector<QStringList> ret; int columns = model->columnCount(); for(int r = 0, rend = model->rowCount(); r < rend; ++r) { ret.push_back(QStringList()); QStringList &b = ret.back(); for(int c = 0; c < columns; ++c) b.push_back(model->data(model->index(r, c), Qt::DisplayRole).toString()); } return RowStore(ret); } QVector<QStringList> ret; QList<LiveNode> const &nodes = livenodes.nodes(); ret.reserve(nodes.size()); for(QList<LiveNode>::const_iterator ni = nodes.begin(), niend = nodes.end(); ni != niend; ++ni) ret.push_back(QStringList(ni->toString())); return RowStore(ret); }
int main( int argc, char ** argv ) { #if defined (FC_OS_LINUX) || defined(FC_OS_BSD) // Make sure to setup the Qt locale system before setting LANG and LC_ALL to C. // which is needed to use the system locale settings. (void)QLocale::system(); // http://www.freecadweb.org/tracker/view.php?id=399 // Because of setting LANG=C the Qt automagic to use the correct encoding // for file names is broken. This is a workaround to force the use of UTF-8 encoding QFile::setEncodingFunction(myEncoderFunc); QFile::setDecodingFunction(myDecoderFunc); // Make sure that we use '.' as decimal point. See also // http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=559846 putenv("LC_NUMERIC=C"); putenv("PYTHONPATH="); #elif defined(FC_OS_MACOSX) (void)QLocale::system(); putenv("LC_NUMERIC=C"); putenv("PYTHONPATH="); #else setlocale(LC_NUMERIC, "C"); _putenv("PYTHONPATH="); #endif #if defined (FC_OS_WIN32) int argc_ = argc; QVector<QByteArray> data; QVector<char *> argv_; // get the command line arguments as unicode string { QCoreApplication app(argc, argv); QStringList args = app.arguments(); for (QStringList::iterator it = args.begin(); it != args.end(); ++it) { data.push_back(it->toUtf8()); argv_.push_back(data.back().data()); } argv_.push_back(0); // 0-terminated string } #endif // Name and Version of the Application App::Application::Config()["ExeName"] = "FreeCAD"; App::Application::Config()["ExeVendor"] = "FreeCAD"; App::Application::Config()["AppDataSkipVendor"] = "true"; App::Application::Config()["MaintainerUrl"] = "http://www.freecadweb.org/wiki/index.php?title=Main_Page"; // set the banner (for logging and console) App::Application::Config()["CopyrightInfo"] = sBanner; App::Application::Config()["AppIcon"] = "freecad"; App::Application::Config()["SplashScreen"] = "freecadsplash"; App::Application::Config()["StartWorkbench"] = "StartWorkbench"; //App::Application::Config()["HiddenDockWindow"] = "Property editor"; App::Application::Config()["SplashAlignment" ] = "Bottom|Left"; App::Application::Config()["SplashTextColor" ] = "#ffffff"; // white App::Application::Config()["SplashInfoColor" ] = "#c8c8c8"; // light grey try { // Init phase =========================================================== // sets the default run mode for FC, starts with gui if not overridden in InitConfig... App::Application::Config()["RunMode"] = "Gui"; // Inits the Application #if defined (FC_OS_WIN32) App::Application::init(argc_, argv_.data()); #else App::Application::init(argc, argv); #endif #if defined(_MSC_VER) // create a dump file when the application crashes std::string dmpfile = App::Application::getUserAppDataDir(); dmpfile += "crash.dmp"; InitMiniDumpWriter(dmpfile); #endif std::map<std::string, std::string>::iterator it = App::Application::Config().find("NavigationStyle"); if (it != App::Application::Config().end()) { ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View"); // if not already defined do it now (for the very first start) std::string style = hGrp->GetASCII("NavigationStyle", it->second.c_str()); hGrp->SetASCII("NavigationStyle", style.c_str()); } Gui::Application::initApplication(); // Only if 'RunMode' is set to 'Gui' do the replacement if (App::Application::Config()["RunMode"] == "Gui") Base::Interpreter().replaceStdOutput(); } catch (const Base::UnknownProgramOption& e) { QApplication app(argc,argv); QString appName = QString::fromAscii(App::Application::Config()["ExeName"].c_str()); QString msg = QString::fromAscii(e.what()); QString s = QLatin1String("<pre>") + msg + QLatin1String("</pre>"); QMessageBox::critical(0, appName, s); exit(1); } catch (const Base::ProgramInformation& e) { QApplication app(argc,argv); QString appName = QString::fromAscii(App::Application::Config()["ExeName"].c_str()); QString msg = QString::fromAscii(e.what()); QString s = QLatin1String("<pre>") + msg + QLatin1String("</pre>"); QMessageBox::information(0, appName, s); exit(0); } catch (const Base::Exception& e) { // Popup an own dialog box instead of that one of Windows QApplication app(argc,argv); QString appName = QString::fromAscii(App::Application::Config()["ExeName"].c_str()); QString msg; msg = QObject::tr("While initializing %1 the following exception occurred: '%2'\n\n" "Python is searching for its files in the following directories:\n%3\n\n" "Python version information:\n%4\n") .arg(appName).arg(QString::fromUtf8(e.what())) .arg(QString::fromUtf8(Py_GetPath())).arg(QString::fromAscii(Py_GetVersion())); const char* pythonhome = getenv("PYTHONHOME"); if (pythonhome) { msg += QObject::tr("\nThe environment variable PYTHONHOME is set to '%1'.") .arg(QString::fromUtf8(pythonhome)); msg += QObject::tr("\nSetting this environment variable might cause Python to fail. " "Please contact your administrator to unset it on your system.\n\n"); } else { msg += QObject::tr("\nPlease contact the application's support team for more information.\n\n"); } QMessageBox::critical(0, QObject::tr("Initialization of %1 failed").arg(appName), msg); exit(100); } catch (...) { // Popup an own dialog box instead of that one of Windows QApplication app(argc,argv); QString appName = QString::fromAscii(App::Application::Config()["ExeName"].c_str()); QString msg = QObject::tr("Unknown runtime error occurred while initializing %1.\n\n" "Please contact the application's support team for more information.\n\n").arg(appName); QMessageBox::critical(0, QObject::tr("Initialization of %1 failed").arg(appName), msg); exit(101); } // Run phase =========================================================== Base::RedirectStdOutput stdcout; Base::RedirectStdLog stdclog; Base::RedirectStdError stdcerr; std::streambuf* oldcout = std::cout.rdbuf(&stdcout); std::streambuf* oldclog = std::clog.rdbuf(&stdclog); std::streambuf* oldcerr = std::cerr.rdbuf(&stdcerr); try { if (App::Application::Config()["RunMode"] == "Gui") Gui::Application::runApplication(); else App::Application::runApplication(); } catch (const Base::SystemExitException&) { exit(0); } catch (const Base::Exception& e) { Base::Console().Error("%s\n", e.what()); } catch (...) { Base::Console().Error("Application unexpectedly terminated\n"); } std::cout.rdbuf(oldcout); std::clog.rdbuf(oldclog); std::cerr.rdbuf(oldcerr); // Destruction phase =========================================================== Base::Console().Log("%s terminating...\n",App::Application::Config()["ExeName"].c_str()); // cleans up App::Application::destruct(); Base::Console().Log("%s completely terminated\n",App::Application::Config()["ExeName"].c_str()); return 0; }
int main( int argc, char ** argv ) { #if defined (FC_OS_LINUX) || defined(FC_OS_BSD) // Make sure to setup the Qt locale system before setting LANG and LC_ALL to C. // which is needed to use the system locale settings. (void)QLocale::system(); #if QT_VERSION < 0x050000 // http://www.freecadweb.org/tracker/view.php?id=399 // Because of setting LANG=C the Qt automagic to use the correct encoding // for file names is broken. This is a workaround to force the use of UTF-8 encoding QFile::setEncodingFunction(myEncoderFunc); QFile::setDecodingFunction(myDecoderFunc); #endif // See https://forum.freecadweb.org/viewtopic.php?f=18&t=20600 // See Gui::Application::runApplication() putenv("LC_NUMERIC=C"); putenv("PYTHONPATH="); #elif defined(FC_OS_MACOSX) (void)QLocale::system(); putenv("PYTHONPATH="); #else _putenv("PYTHONPATH="); // https://forum.freecadweb.org/viewtopic.php?f=4&t=18288 // https://forum.freecadweb.org/viewtopic.php?f=3&t=20515 const char* fc_py_home = getenv("FC_PYTHONHOME"); if (fc_py_home) _putenv_s("PYTHONHOME", fc_py_home); else _putenv("PYTHONHOME="); #endif #if defined (FC_OS_WIN32) int argc_ = argc; QVector<QByteArray> data; QVector<char *> argv_; // get the command line arguments as unicode string { QCoreApplication app(argc, argv); QStringList args = app.arguments(); for (QStringList::iterator it = args.begin(); it != args.end(); ++it) { data.push_back(it->toUtf8()); argv_.push_back(data.back().data()); } argv_.push_back(0); // 0-terminated string } #endif #if PY_MAJOR_VERSION >= 3 #if defined(_MSC_VER) && _MSC_VER <= 1800 // See InterpreterSingleton::init Redirection out(stdout), err(stderr), inp(stdin); #endif #endif // PY_MAJOR_VERSION // Name and Version of the Application App::Application::Config()["ExeName"] = "FreeCAD"; App::Application::Config()["ExeVendor"] = "FreeCAD"; App::Application::Config()["AppDataSkipVendor"] = "true"; App::Application::Config()["MaintainerUrl"] = "http://www.freecadweb.org/wiki/Main_Page"; // set the banner (for logging and console) App::Application::Config()["CopyrightInfo"] = sBanner; App::Application::Config()["AppIcon"] = "freecad"; App::Application::Config()["SplashScreen"] = "freecadsplash"; App::Application::Config()["StartWorkbench"] = "StartWorkbench"; //App::Application::Config()["HiddenDockWindow"] = "Property editor"; App::Application::Config()["SplashAlignment" ] = "Bottom|Left"; App::Application::Config()["SplashTextColor" ] = "#ffffff"; // white App::Application::Config()["SplashInfoColor" ] = "#c8c8c8"; // light grey try { // Init phase =========================================================== // sets the default run mode for FC, starts with gui if not overridden in InitConfig... App::Application::Config()["RunMode"] = "Gui"; App::Application::Config()["Console"] = "0"; // Inits the Application #if defined (FC_OS_WIN32) App::Application::init(argc_, argv_.data()); #else App::Application::init(argc, argv); #endif #if defined(_MSC_VER) // create a dump file when the application crashes std::string dmpfile = App::Application::getUserAppDataDir(); dmpfile += "crash.dmp"; InitMiniDumpWriter(dmpfile); #endif std::map<std::string, std::string>::iterator it = App::Application::Config().find("NavigationStyle"); if (it != App::Application::Config().end()) { ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View"); // if not already defined do it now (for the very first start) std::string style = hGrp->GetASCII("NavigationStyle", it->second.c_str()); hGrp->SetASCII("NavigationStyle", style.c_str()); } Gui::Application::initApplication(); // Only if 'RunMode' is set to 'Gui' do the replacement if (App::Application::Config()["RunMode"] == "Gui") Base::Interpreter().replaceStdOutput(); } catch (const Base::UnknownProgramOption& e) { QApplication app(argc,argv); QString appName = QString::fromLatin1(App::Application::Config()["ExeName"].c_str()); QString msg = QString::fromLatin1(e.what()); QString s = QLatin1String("<pre>") + msg + QLatin1String("</pre>"); QMessageBox::critical(0, appName, s); exit(1); } catch (const Base::ProgramInformation& e) { QApplication app(argc,argv); QString appName = QString::fromLatin1(App::Application::Config()["ExeName"].c_str()); QString msg = QString::fromUtf8(e.what()); QString s = QLatin1String("<pre>") + msg + QLatin1String("</pre>"); QMessageBox msgBox; msgBox.setIcon(QMessageBox::Information); msgBox.setWindowTitle(appName); msgBox.setDetailedText(msg); msgBox.setText(s); msgBox.exec(); exit(0); } catch (const Base::Exception& e) { // Popup an own dialog box instead of that one of Windows QApplication app(argc,argv); QString appName = QString::fromLatin1(App::Application::Config()["ExeName"].c_str()); QString msg; msg = QObject::tr("While initializing %1 the following exception occurred: '%2'\n\n" "Python is searching for its files in the following directories:\n%3\n\n" "Python version information:\n%4\n") .arg(appName).arg(QString::fromUtf8(e.what())) #if PY_MAJOR_VERSION >= 3 #if PY_MINOR_VERSION >= 5 .arg(QString::fromUtf8(Py_EncodeLocale(Py_GetPath(),NULL))).arg(QString::fromLatin1(Py_GetVersion())); #else .arg(QString::fromUtf8(_Py_wchar2char(Py_GetPath(),NULL))).arg(QString::fromLatin1(Py_GetVersion())); #endif #else .arg(QString::fromUtf8(Py_GetPath())).arg(QString::fromLatin1(Py_GetVersion()));
void GraphConnection::render(QPainter &painter) { assert(_impl); //dont draw connections with missing endpoints if (not _impl->outputEp.isValid()) return; if (not _impl->inputEp.isValid()) return; //query the connectable info const auto outputAttrs = _impl->outputEp.getConnectableAttrs(); const auto inputAttrs = _impl->inputEp.getConnectableAttrs(); //make the minimal output protrusion const auto op0 = outputAttrs.point; QTransform otrans; otrans.rotate(outputAttrs.rotation); const auto op1 = outputAttrs.point + otrans.map(QPointF(GraphConnectionMinPling, 0)); //make the minimal input protrusion const auto ip0 = inputAttrs.point; QTransform itrans; itrans.rotate(inputAttrs.rotation + 180); const auto ip1 = inputAttrs.point + itrans.map(QPointF(GraphConnectionMinPling+GraphConnectionArrowLen, 0)); //create a path for the connection lines QVector<QPointF> points; points.push_back(op0); points.push_back(op1); makeLines(points, op1, outputAttrs.rotation, ip1, inputAttrs.rotation + 180); points.push_back(ip1); points.push_back(ip0); //create a painter path with curves for corners QPainterPath path(points.front()); for (int i = 1; i < points.size()-1; i++) { const auto last = points[i-1]; const auto curr = points[i]; const auto next = points[i+1]; path.lineTo(lineShorten(QLineF(last, curr)).p2()); path.quadTo(curr, lineShorten(QLineF(next, curr)).p2()); } path.lineTo(points.back()); //draw the painter path QColor color(getSelected()?GraphConnectionHighlightColor:GraphConnectionDefaultColor); painter.setBrush(Qt::NoBrush); QPen pen(color); pen.setWidthF(GraphConnectionGirth); painter.setPen(pen); painter.drawPath(path); _impl->points = points; //create arrow head QTransform trans0; trans0.rotate(inputAttrs.rotation + GraphConnectionArrowAngle); QTransform trans1; trans1.rotate(inputAttrs.rotation - GraphConnectionArrowAngle); const auto p0 = trans0.map(QPointF(-GraphConnectionArrowLen, 0)); const auto p1 = trans1.map(QPointF(-GraphConnectionArrowLen, 0)); QPolygonF arrowHead; arrowHead << ip0 << (ip0+p0) << (ip0+p1); painter.setBrush(QBrush(color)); painter.drawPolygon(arrowHead); _impl->arrowHead = arrowHead; }
/*! Draw the shape in response to an update event. */ void QgsRubberBand::paint( QPainter* p ) { if ( !mPoints.isEmpty() ) { p->setBrush( mBrush ); p->setPen( mPen ); Q_FOREACH ( const QList<QgsPoint>& line, mPoints ) { QVector<QPointF> pts; Q_FOREACH ( const QgsPoint& pt, line ) { const QPointF cur = toCanvasCoordinates( QgsPoint( pt.x() + mTranslationOffsetX, pt.y() + mTranslationOffsetY ) ) - pos(); if ( pts.empty() || std::abs( pts.back().x() - cur.x() ) > 1 || std::abs( pts.back().y() - cur.y() ) > 1 ) pts.append( cur ); } switch ( mGeometryType ) { case QgsWkbTypes::PolygonGeometry: { p->drawPolygon( pts ); } break; case QgsWkbTypes::PointGeometry: { Q_FOREACH ( QPointF pt, pts ) { double x = pt.x(); double y = pt.y(); qreal s = ( mIconSize - 1 ) / 2.0; switch ( mIconType ) { case ICON_NONE: break; case ICON_CROSS: p->drawLine( QLineF( x - s, y, x + s, y ) ); p->drawLine( QLineF( x, y - s, x, y + s ) ); break; case ICON_X: p->drawLine( QLineF( x - s, y - s, x + s, y + s ) ); p->drawLine( QLineF( x - s, y + s, x + s, y - s ) ); break; case ICON_BOX: p->drawLine( QLineF( x - s, y - s, x + s, y - s ) ); p->drawLine( QLineF( x + s, y - s, x + s, y + s ) ); p->drawLine( QLineF( x + s, y + s, x - s, y + s ) ); p->drawLine( QLineF( x - s, y + s, x - s, y - s ) ); break; case ICON_FULL_BOX: p->drawRect( x - s, y - s, mIconSize, mIconSize ); break; case ICON_CIRCLE: p->drawEllipse( x - s, y - s, mIconSize, mIconSize ); break; } } } break; case QgsWkbTypes::LineGeometry: default: { p->drawPolyline( pts ); } break; }
/// Display a form layout with an edit box /// \param const QString& title title to display /// \param const QScriptValue form to display (array containing labels and values) /// \return QScriptValue result form (unchanged is dialog canceled) QScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptValue form) { if (form.isArray() && form.property("length").toInt32() > 0) { QDialog* editDialog = new QDialog(Application::getInstance()->getWindow()); editDialog->setWindowTitle(title); QVBoxLayout* layout = new QVBoxLayout(); editDialog->setLayout(layout); QScrollArea* area = new QScrollArea(); layout->addWidget(area); area->setWidgetResizable(true); QWidget* container = new QWidget(); QFormLayout* formLayout = new QFormLayout(); container->setLayout(formLayout); container->sizePolicy().setHorizontalStretch(1); formLayout->setRowWrapPolicy(QFormLayout::DontWrapRows); formLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); formLayout->setFormAlignment(Qt::AlignHCenter | Qt::AlignTop); formLayout->setLabelAlignment(Qt::AlignLeft); area->setWidget(container); QVector<QLineEdit*> edits; for (int i = 0; i < form.property("length").toInt32(); ++i) { QScriptValue item = form.property(i); edits.push_back(new QLineEdit(item.property("value").toString())); formLayout->addRow(item.property("label").toString(), edits.back()); } QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok); connect(buttons, SIGNAL(accepted()), editDialog, SLOT(accept())); layout->addWidget(buttons); if (editDialog->exec() == QDialog::Accepted) { for (int i = 0; i < form.property("length").toInt32(); ++i) { QScriptValue item = form.property(i); QScriptValue value = item.property("value"); bool ok = true; if (value.isNumber()) { value = edits.at(i)->text().toDouble(&ok); } else if (value.isString()) { value = edits.at(i)->text(); } else if (value.isBool()) { if (edits.at(i)->text() == "true") { value = true; } else if (edits.at(i)->text() == "false") { value = false; } else { ok = false; } } if (ok) { item.setProperty("value", value); form.setProperty(i, item); } } } delete editDialog; } return form; }
void QSvgText::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); qreal oldOpacity = p->opacity(); p->setOpacity(oldOpacity * states.fillOpacity); // Force the font to have a size of 100 pixels to avoid truncation problems // when the font is very small. qreal scale = 100.0 / p->font().pointSizeF(); Qt::Alignment alignment = states.textAnchor; QTransform oldTransform = p->worldTransform(); p->scale(1 / scale, 1 / scale); qreal y = 0; bool initial = true; qreal px = m_coord.x() * scale; qreal py = m_coord.y() * scale; QSizeF scaledSize = m_size * scale; if (m_type == TEXTAREA) { if (alignment == Qt::AlignHCenter) px += scaledSize.width() / 2; else if (alignment == Qt::AlignRight) px += scaledSize.width(); } QRectF bounds; if (m_size.height() != 0) bounds = QRectF(0, py, 1, scaledSize.height()); // x and width are not used. bool appendSpace = false; QVector<QString> paragraphs; QStack<QTextCharFormat> formats; QVector<QList<QTextLayout::FormatRange> > formatRanges; paragraphs.push_back(QString()); formatRanges.push_back(QList<QTextLayout::FormatRange>()); for (int i = 0; i < m_tspans.size(); ++i) { if (m_tspans[i] == LINEBREAK) { if (m_type == TEXTAREA) { if (paragraphs.back().isEmpty()) { QFont font = p->font(); font.setPixelSize(font.pointSizeF() * scale); QTextLayout::FormatRange range; range.start = 0; range.length = 1; range.format.setFont(font); formatRanges.back().append(range); paragraphs.back().append(QLatin1Char(' '));; } appendSpace = false; paragraphs.push_back(QString()); formatRanges.push_back(QList<QTextLayout::FormatRange>()); } } else { WhitespaceMode mode = m_tspans[i]->whitespaceMode(); m_tspans[i]->applyStyle(p, states); QFont font = p->font(); font.setPixelSize(font.pointSizeF() * scale); QString newText(m_tspans[i]->text()); newText.replace(QLatin1Char('\t'), QLatin1Char(' ')); newText.replace(QLatin1Char('\n'), QLatin1Char(' ')); bool prependSpace = !appendSpace && !m_tspans[i]->isTspan() && (mode == Default) && !paragraphs.back().isEmpty() && newText.startsWith(QLatin1Char(' ')); if (appendSpace || prependSpace) paragraphs.back().append(QLatin1Char(' ')); bool appendSpaceNext = (!m_tspans[i]->isTspan() && (mode == Default) && newText.endsWith(QLatin1Char(' '))); if (mode == Default) { newText = newText.simplified(); if (newText.isEmpty()) appendSpaceNext = false; } QTextLayout::FormatRange range; range.start = paragraphs.back().length(); range.length = newText.length(); range.format.setFont(font); range.format.setTextOutline(p->pen()); range.format.setForeground(p->brush()); if (appendSpace) { Q_ASSERT(!formatRanges.back().isEmpty()); ++formatRanges.back().back().length; } else if (prependSpace) { --range.start; ++range.length; } formatRanges.back().append(range); appendSpace = appendSpaceNext; paragraphs.back() += newText; m_tspans[i]->revertStyle(p, states); } } if (states.svgFont) { // SVG fonts not fully supported... QString text = paragraphs.front(); for (int i = 1; i < paragraphs.size(); ++i) { text.append(QLatin1Char('\n')); text.append(paragraphs[i]); } states.svgFont->draw(p, m_coord * scale, text, p->font().pointSizeF() * scale, states.textAnchor); } else { for (int i = 0; i < paragraphs.size(); ++i) { QTextLayout tl(paragraphs[i]); QTextOption op = tl.textOption(); op.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); tl.setTextOption(op); tl.setAdditionalFormats(formatRanges[i]); tl.beginLayout(); forever { QTextLine line = tl.createLine(); if (!line.isValid()) break; if (m_size.width() != 0) line.setLineWidth(scaledSize.width()); } tl.endLayout(); bool endOfBoundsReached = false; for (int i = 0; i < tl.lineCount(); ++i) { QTextLine line = tl.lineAt(i); qreal x = 0; if (alignment == Qt::AlignHCenter) x -= 0.5 * line.naturalTextWidth(); else if (alignment == Qt::AlignRight) x -= line.naturalTextWidth(); if (initial && m_type == TEXT) y -= line.ascent(); initial = false; line.setPosition(QPointF(x, y)); // Check if the current line fits into the bounding rectangle. if ((m_size.width() != 0 && line.naturalTextWidth() > scaledSize.width()) || (m_size.height() != 0 && y + line.height() > scaledSize.height())) { // I need to set the bounds height to 'y-epsilon' to avoid drawing the current // line. Since the font is scaled to 100 units, 1 should be a safe epsilon. bounds.setHeight(y - 1); endOfBoundsReached = true; break; } y += 1.1 * line.height(); } tl.draw(p, QPointF(px, py), QVector<QTextLayout::FormatRange>(), bounds); if (endOfBoundsReached) break; } } p->setWorldTransform(oldTransform, false); p->setOpacity(oldOpacity); revertStyle(p, states); }
int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QString programName = QFileInfo( QCoreApplication::applicationFilePath()).fileName(); // Retrieve command line arguments from Qt and parse options int appArgC = a.arguments().size(); QVector<QByteArray> arguments; char** appArgV = new char*[appArgC]; for (int i = 0; i < appArgC; ++i) { arguments.push_back(a.arguments()[i].toLocal8Bit()); appArgV[i] = arguments.back().data(); } const char shortOptions[] = "h"; option longOptions[] = { {"help", 0, NULL, 'h'} }; opterr = 0; // disable getopt error messages int lastOption; while ((lastOption = getopt_long(appArgC, appArgV, shortOptions, longOptions, NULL)) != -1) { switch (lastOption) { case '?': cerr << QString("%1: invalid option -- '%2'\n") .arg(programName) .arg(static_cast<char>(optopt)); cerr << endl; printHelp(programName); return 1; case 'h': printHelp(programName); return 0; default: abort(); } } if (optind == appArgC) { printHelp(programName); return 99; } // Map the RIFF file into memory QFile rifffile(appArgV[optind]); if (! rifffile.open(QIODevice::ReadOnly)) { cerr << QString("%1: %2\n").arg(programName).arg(rifffile.errorString()); return 10; } // QFile::map doesn't allow options like MAP_HUGETLB, MAP_PRIVATE or MAP_LOCKED // but it is more portable between different operating systems than mmap(). // Previously, we tried to use MAP_HUGETLB with mmap() syscall but it is only // valid for anonymous memory. uchar* buffer = rifffile.map(0, rifffile.size()); if(buffer == NULL) { cerr << QString("%1: %2\n") .arg(programName) .arg(rifffile.errorString()); return 11; } riff::RiffChunk<>* chunk = reinterpret_cast<riff::RiffChunk<>*>(buffer); if (! chunk->hasTypeRiff()) { cerr << QString("%1: '%2' is not a valid RIFF file\n") .arg(programName) .arg(rifffile.fileName()); return 20; } // Traverse the RIFF file and print its structure traverseRiff(chunk->castTo<riff::RiffList<> >(), 0); // return a.exec(); }
bool RTRModel::loadModelFromObjFile(const QString& filePath) { QFileInfo info(filePath); modelPath = info.dir().path(); QFile objModelFile(filePath); if(!objModelFile.open(QIODevice::ReadOnly)) { return false; } QTextStream objModelStream(&objModelFile); QString currentObjectName = ""; QString currentGroupName = ""; QString materialName = ""; QVector<RTRModelVertex*> tempVertexPositions; QVector<RTRVector3D> tempVertexNormals; QVector<RTRVector2D> tempVertexUVPositions; bool currentSmoothShading = true; while(!objModelStream.atEnd()) { //Read a line, spaces and begin and end are trimmed QString line = objModelStream.readLine().trimmed(); //Ignore empty lines and comment lines if (line.isEmpty()) continue; if (line[0] == '#') continue; QStringList param = line.split(' ', QString::SkipEmptyParts); QString command = param[0]; command.toLower(); param.removeFirst(); if (command == "mtllib") loadMaterialLibraryFromMtlFile(modelPath + "/" + param[0]); else if (command == "usemtl") materialName = param[0]; else if (command == "o") currentObjectName = param[0]; else if (command == "g") { currentGroupName = param[0]; } else if (command == "s") { if (param[0] == "off") currentSmoothShading = false; else currentSmoothShading = true; } else if (command == "v") { tempVertexPositions.append( addVertex(param[0].toDouble(), param[1].toDouble(), param[2].toDouble())); } else if (command == "vn") { tempVertexNormals.append(RTRVector3D(param[0].toDouble(), param[1].toDouble(), param[2].toDouble())); tempVertexNormals.back().vectorNormalize(); } else if (command == "vt") { tempVertexUVPositions.append(RTRVector2D(param[0].toDouble(), param[1].toDouble())); } else if (command == "f") { RTRModelPolygen* poly = new RTRModelPolygen(); poly->objectName = currentObjectName; poly->groupName = currentGroupName; poly->materialName = materialName; poly->smoothShading = currentSmoothShading; for (int i = 0; i < param.size(); i++) { QStringList list = param[i].split("/"); switch (list.size()) { case 1: poly->vertices.append(tempVertexPositions[list[0].toInt() - 1]); break; case 2: poly->vertices.append(tempVertexPositions[list[0].toInt() - 1]); poly->uvMaps.append(tempVertexUVPositions[list[1].toInt() - 1]); break; case 3: poly->vertices.append(tempVertexPositions[list[0].toInt() - 1]); if (!list[1].isEmpty()) poly->uvMaps.append(tempVertexUVPositions[list[1].toInt() - 1]); poly->normals.append(tempVertexNormals[list[2].toInt() - 1]); break; default: break; } } polygens.insert(poly); } else { qDebug() << "Ignoring Unsupported Line : " << command << param; } } objModelFile.close(); return true; }
QVector<Vector3> SimilarSampler::FaceSamples(SurfaceMeshModel * m, int sampleNum, QVector<Vector3> & samplesNormals, double * avgSpacing) { QVector<Vector3> samples; // Compute face areas SurfaceMeshHelper h( m ); h.computeFaceAreas(); ScalarFaceProperty farea = m->face_property<Scalar>(FAREA); Scalar area = 0; for(auto f : m->faces()) area += farea[f]; // Compute edge lengths ScalarEdgeProperty elength = h.computeEdgeLengths(); m->update_face_normals(); Vector3FaceProperty fnormals = m->get_face_property<Vector3>(FNORMAL); Scalar samplePerAreaUnit = sampleNum / area; // Mesh points Vector3VertexProperty points = h.getVector3VertexProperty(VPOINT); // Similar Triangles sampling for(auto f : m->faces()) { // Collect vector of triangle points, and map to vertices std::vector<Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d> > triangle, virtualTri; QMap<Surface_mesh::Vertex, int> verts; for(auto vit : m->vertices(f)) { verts[vit] = triangle.size(); triangle.push_back(points[vit]); } virtualTri = triangle; // Force virtual triangle to be isosceles { QMap<Surface_mesh::Halfedge,double> edgeMap; // Classify edges by their lengths for(auto hj : m->halfedges(f)) edgeMap[hj] = elength[m->edge(hj)]; QList< QPair<double,Surface_mesh::Halfedge> > edges = sortQMapByValue(edgeMap); Surface_mesh::Halfedge S = edges.at(0).second, M = edges.at(1).second, L = edges.at(2).second; Surface_mesh::Vertex vP = m->to_vertex(m->next_halfedge(L)); Surface_mesh::Vertex v0 = (vP == m->to_vertex(S)) ? m->from_vertex(S) : m->to_vertex(S); Surface_mesh::Vertex vM = (vP == m->to_vertex(M)) ? m->from_vertex(M) : m->to_vertex(M); Eigen::Vector3d deltaS = (points[vP] - points[v0]).normalized(); Eigen::Vector3d deltaL = (points[vM] - points[v0]).normalized(); // Push vertex towards triangle with two equal edges virtualTri[ verts[vP] ] = points[v0] + (deltaS * elength[m->edge(M)]); // Shrink triangle to avoid sampling edges triangle[ verts[vP] ] = points[vP] + (-deltaS * elength[m->edge(S)] * 0.001); triangle[ verts[vM] ] = points[vM] + (-deltaL * elength[m->edge(L)] * 0.001); } double varea = 0.5 * Vector3(virtualTri[1] - virtualTri[0]).cross(Vector3(virtualTri[2] - virtualTri[0])).norm(); // compute # samples in the current face int n_samples = (int) (0.5 * varea * samplePerAreaUnit); // Minimum number of samples per face n_samples = qMax(n_samples, 2); if(n_samples > 1) { int n_samples_per_edge = (int)((sqrt(1.0 + 8.0 * (Scalar)n_samples) + 5.0) / 2.0); Scalar segmentNum = n_samples_per_edge - 1 ; Scalar segmentLen = 1.0 / segmentNum; // face sampling for(int i = 1; i < (n_samples_per_edge - 1); i++) { for(int j = 1; j < (n_samples_per_edge - 1) - i; j++) { Scalar uvw[] = {i*segmentLen, j*segmentLen, 1.0 - (i*segmentLen + j*segmentLen)}; // Get point from current barycentric coordinate Eigen::Vector3d p = Eigen::Vector3d::Zero(); for(int vi = 0; vi < 3; vi++) p = p + (virtualTri[vi] * uvw[vi]); Eigen::Vector3d coord = barycentric(p, triangle[0], triangle[1], triangle[2]); if( !isValidBaryCoord (coord) ) continue; samples.push_back( p ); samplesNormals.push_back( fnormals[f] ); if(avgSpacing && j > 1 && samples.size() > 1) { double dist = (samples.back() - samples[samples.size()-2]).norm(); if(dist != 0.0) *avgSpacing = dist; } } } } } return samples; }