BlinkenArea - GitList
Repositories
Blog
Wiki
libflexipix
Code
Commits
Branches
Tags
Search
Tree:
0e2d779
Branches
Tags
master
v1.0.0
v1.0.1
v1.0.2
v1.0.3
v1.0.4
v1.0.5
v1.0.6
v1.0.7
v1.0.8
libflexipix
config_gen
src
main.cpp
adaptions for gcc 5
Stefan Schuermans
commited
0e2d779
at 2017-02-11 09:44:10
main.cpp
Blame
History
Raw
/* * FlexiPix config file generator * * Copyright 2010 Stefan Schuermans <stefan schuermans info> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License. * * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <algorithm> #include <dime/entities/Entity.h> #include <dime/Input.h> #include <dime/Model.h> #include <dime/State.h> #include <fstream> #include <iostream> #include <map> #include <string> #include "chain.h" #include "constants.h" #include "distri.h" #include "layer.h" #include "line.h" #include "pixel.h" #include "point.h" Layer gLayerVideo, gLayerPixel, gLayerNetwork; std::map<unsigned int, Layer> gLayerCables, gLayerDistributors; Layer gLayerCable; /** * @brief enumerate a entitiy in the DXF file * @param[in] state current state of libdime * @param[in] entity pointer to entity * @param[in] vp_ctx context pointer * @return if to continue enumeration */ bool cbEntity(const class dimeState * const state, class dimeEntity *entity, void *vp_ctx) { (void)vp_ctx; // get layer std::string strLayerName = entity->getLayerName(); Layer * pLayer; if (strLayerName == "video") pLayer = &gLayerVideo; else if (strLayerName == "pixel") pLayer = &gLayerPixel; else if (strLayerName == "network") pLayer = &gLayerNetwork; else if (strLayerName.substr(0, 6) == "cable ") { unsigned int no = 0; if (sscanf(strLayerName.substr(6).c_str(), "%x", &no) != 1) no = 0; // cable 0 by default pLayer = &gLayerCables[no]; } else if (strLayerName.substr(0, 12) == "distributor ") { unsigned int no = 0; if (sscanf(strLayerName.substr(12).c_str(), "%x", &no) != 1) no = 0; // distributor 0 by default pLayer = &gLayerDistributors[no]; } else return true; // get transformation matrix dimeMatrix matrix; state->getMatrix(matrix); // get geometry data dimeArray<dimeVec3f> vertices; dimeArray<int> indices; dimeVec3f extrusionDir; dxfdouble thickness; entity->extractGeometry(vertices, indices, extrusionDir, thickness); // transform geometry data for (int i = 0; i < vertices.count(); ++i) matrix.multMatrixVec(vertices[i]); // build object from geometry data Object *pObject = new Object; for (int i = 1; i < vertices.count(); ++i) { Line *pLine = new Line(Point(vertices[i - 1].x, vertices[i - 1].y), Point(vertices[i].x, vertices[i].y)); if (pLine->length() >= EPSILON) // ignore dots pObject->add(pLine); else { std::cout << "ignoring dot at " << pLine->mStart.mX << "," << pLine->mStart.mY << std::endl; delete pLine; } } // build object into layer pLayer->build(pObject); return true; } /** * @brief create a chain * @param[in] chain chain to create * @param[in] pObjCable cable to first pixel * @return 0 on success, -1 on error */ int createChain(Chain &chain, const Object *pObjCable) { // add all pixels const Object *pObjPixel = NULL; while (true) { // find pixels connected to cable std::vector<Layer::Intersection> intersectsPixels; gLayerPixel.getIntersections(pObjCable, intersectsPixels); // remove last pixel from results std::vector<Layer::Intersection>::iterator itPixel; for (itPixel = intersectsPixels.begin(); itPixel != intersectsPixels.end(); ++itPixel) { if (itPixel->pObj == pObjPixel) { itPixel = intersectsPixels.erase(itPixel); if (itPixel == intersectsPixels.end()) break; } } // end of chain if (intersectsPixels.size() < 1) return 0; // more than one next pixel if (intersectsPixels.size() > 1) { std::cerr << "pixel cable connects multiple pixels (" << intersectsPixels[0].pt.mX << "," << intersectsPixels[0].pt.mY << ")" << std::endl; return -1; } // pixel found pObjPixel = intersectsPixels[0].pObj; // add pixel to chain chain.mPixels.push_back(Pixel(pObjPixel)); // find cables connected to pixel std::vector<Layer::Intersection> intersectsCables; gLayerCable.getIntersections(pObjPixel, intersectsCables); // remove last cable from results std::vector<Layer::Intersection>::iterator itCable; for (itCable = intersectsCables.begin(); itCable != intersectsCables.end(); ++itCable) { if (itCable->pObj == pObjCable) { itCable = intersectsCables.erase(itCable); if (itCable == intersectsCables.end()) break; } } // end of chain if (intersectsCables.size() < 1) return 0; // more than one next pixel if (intersectsCables.size() > 1) { std::cerr << "pixel connected to multiple pixel cables (" << intersectsCables[0].pt.mX << "," << intersectsCables[0].pt.mY << ")" << std::endl; return -1; } // next cable found pObjCable = intersectsCables[0].pObj; } // while (true) } /// sort helper for distributor/cables intersections bool intersectsCablesSort(const Layer::Intersection& i1, const Layer::Intersection& i2) { return i1.pt.abs_sq() < i2.pt.abs_sq(); } /** * @brief create a distributor * @param[in] distri distributor to create * @param[in] pLayer layer containing distributor * @param[in] pixels number of pixels per chain * @return 0 on success, -1 on error */ int createDistri(Distri &distri, const Layer *pLayer, unsigned int pixels) { // must have exactly one object if (pLayer->mObjects.size() != 1) { std::cerr << "layer of distributor " << std::hex << distri.mNo << "contains no or multiple objects" << std::endl; return -1; } const Object *pObjDistri = pLayer->mObjects[0]; // get location of network connection std::vector<Layer::Intersection> intersectsNet; gLayerNetwork.getIntersections(pObjDistri, intersectsNet); if (intersectsNet.size() != 1) { std::cerr << "distributor " << std::hex << distri.mNo << "has no or multiple network connections" << std::endl; return -1; } Point ptNetwork = intersectsNet[0].pt; // get cables to pixel chains std::vector<Layer::Intersection> intersectsCables; gLayerCable.getIntersections(pObjDistri, intersectsCables); // sort cables according to distance to network std::vector<Layer::Intersection>::iterator itIntersect; for (itIntersect = intersectsCables.begin(); itIntersect != intersectsCables.end(); ++itIntersect) itIntersect->pt -= ptNetwork; std::sort(intersectsCables.begin(), intersectsCables.end(), intersectsCablesSort); // create chains bool err = false; for (itIntersect = intersectsCables.begin(); itIntersect != intersectsCables.end(); ++itIntersect) { distri.mChains.push_back(Chain(pixels)); if (createChain(distri.mChains.back(), itIntersect->pObj) != 0) err = true; } return err ? -1 : 0; } /** * @brief write config file * @param[in] width width of video in pixels * @param[in] height height of video in pixels * @param[in] distris distributor objects */ int writeCfg(unsigned int width, unsigned int height, const std::vector<Distri> &distris, const std::string & strCfgFileName) { //open output file std::ofstream strm(strCfgFileName.c_str(), std::ios::out); if (!strm.is_open()) { std::cerr << "could not open \"" << strCfgFileName << "\" for wrinting" << std::endl; return -1; } // video size strm << "size = " << width << "," << height << std::endl << std::endl; // distributors std::vector<Distri>::const_iterator itD; for (itD = distris.begin(); itD != distris.end(); ++itD) itD->writeDistri(strm); strm << std::endl; // mappings for (itD = distris.begin(); itD != distris.end(); ++itD) itD->writeMapping(strm); strm << std::endl; // pixels for (itD = distris.begin(); itD != distris.end(); ++itD) itD->writePixels(strm); strm << std::endl; strm.close(); return 0; } /** * @brief main program * @param[in] argc number of parameters * @param[in] argv parameter values * @return 0 on success, -1 on error */ int main(int argc, char *argv[]) { // get parameters if (argc < 7) { std::cerr << "FlexiPix config file generator " << FLPCG_VER_MAJ << "." << FLPCG_VER_MIN << "." << FLPCG_VER_REV << std::endl << "usage:" << std::endl << " " << argv[0] << " \\" << std::endl << " <schematic_drawing.dxf> <width> <height> \\" << std::endl << " <chains> <pixels> <config.flp>" << std::endl; return -1; } std::string strDxfFileName = argv[1]; unsigned int width = atoi(argv[2]); unsigned int height = atoi(argv[3]); unsigned int chains = atoi(argv[4]); unsigned int pixels = atoi(argv[5]); std::string strCfgFileName = argv[6]; // read DXF file dimeInput in; if (!in.setFile(strDxfFileName.c_str())) { std::cerr << "error opening file \"" << strDxfFileName << "\" for reading" << std::endl; return -1; } dimeModel model; if (!model.read(&in)) { std::cerr << "DXF read error in line " << in.getFilePosition() << " of file \"" << strDxfFileName << "\"" << std::endl; return -1; } // enumerate all entities model.traverseEntities(cbEntity, NULL); // merge all cable layers std::map<unsigned int, Layer>::iterator itCable; for (itCable = gLayerCables.begin(); itCable != gLayerCables.end(); ++itCable) gLayerCable.merge(&itCable->second); // gLayerCables[] is now empty and will not be used any more // output some information std::cout << "video: " << gLayerVideo.mObjects.size() << std::endl; std::cout << "pixel: " << gLayerPixel.mObjects.size() << std::endl; std::cout << "cable: " << gLayerCable.mObjects.size() << std::endl; std::cout << "network: " << gLayerNetwork.mObjects.size() << std::endl; std::cout << "distributor:" << std::endl; std::map<unsigned int, Layer>::const_iterator itDistri; for (itDistri = gLayerDistributors.begin(); itDistri != gLayerDistributors.end(); ++itDistri) std::cout << " " << itDistri->first << ": " << itDistri->second.mObjects.size() << std::endl; // get origin and size of pixels in video Box boundsVideo; gLayerVideo.getBounds(boundsVideo); Point ptPixel0(boundsVideo.mBL.mX, boundsVideo.mTR.mY); Point ptPixelSz = boundsVideo.mTR - boundsVideo.mBL; ptPixelSz.mX /= (double)width; ptPixelSz.mY /= (double)height; ptPixelSz.mY *= -1; std::cout << "video bounds: " << boundsVideo.mBL.mX << "," << boundsVideo.mBL.mY << " " << boundsVideo.mTR.mX << "," << boundsVideo.mTR.mY << std::endl; // create distributors bool err = false; std::vector<Distri> distris; for (itDistri = gLayerDistributors.begin(); itDistri != gLayerDistributors.end(); ++itDistri) { distris.push_back(Distri(itDistri->first, chains, pixels)); if (createDistri(distris.back(), &itDistri->second, pixels) != 0) err = true; } // obtain pixel coordinates std::vector<Distri>::iterator itD; for (itD = distris.begin(); itD != distris.end(); ++itD) if (itD->pixCoord(ptPixel0, ptPixelSz, width, height) != 0) err = true; // write config file if (writeCfg(width, height, distris, strCfgFileName) != 0) err = true; // output message if errors were detected if (err) { std::cerr << "ERRORs were found" << std::endl; return -1; } return 0; }