e81fd099f82751ae7c8013febca43d81f77e664e
Stefan Schuermans add config file generator

Stefan Schuermans authored 7 years ago

1) /*
2)  * FlexiPix config file generator
3)  *
4)  * Copyright 2010 Stefan Schuermans <stefan schuermans info>
5)  *
6)  * This program is free software: you can redistribute it and/or modify
7)  * it under the terms of the GNU General Public License as published by
8)  * the Free Software Foundation, version 3 of the License.
9)  *
10)  *
11)  * This program is distributed in the hope that it will be useful,
12)  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13)  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14)  * GNU General Public License for more details.
15)  *
16)  * You should have received a copy of the GNU Lesser General Public License
17)  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18)  */
19) 
20) #include <algorithm>
21) #include <dime/entities/Entity.h>
22) #include <dime/Input.h>
23) #include <dime/Model.h>
24) #include <dime/State.h>
25) #include <fstream>
26) #include <iostream>
27) #include <map>
28) #include <string>
29) 
30) #include "chain.h"
31) #include "constants.h"
32) #include "distri.h"
33) #include "layer.h"
34) #include "line.h"
35) #include "pixel.h"
36) #include "point.h"
37) 
38) Layer gLayerVideo, gLayerPixel, gLayerNetwork;
39) std::map<unsigned int, Layer> gLayerCables, gLayerDistributors;
40) Layer gLayerCable;
41) 
42) /**
43)  * @brief enumerate a entitiy in the DXF file
44)  * @param[in] state current state of libdime
45)  * @param[in] entity pointer to entity
46)  * @param[in] vp_ctx context pointer
47)  * @return if to continue enumeration
48)  */
49) bool cbEntity(const class dimeState * const state, class dimeEntity *entity,
50)             void *vp_ctx)
51) {
52)   (void)vp_ctx;
53) 
54)   // get layer
55)   std::string strLayerName = entity->getLayerName();
56)   Layer * pLayer;
Stefan Schuermans support decimal and hexadec...

Stefan Schuermans authored 7 years ago

57)   if (strLayerName == "video") {
Stefan Schuermans add config file generator

Stefan Schuermans authored 7 years ago

58)     pLayer = &gLayerVideo;
Stefan Schuermans support decimal and hexadec...

Stefan Schuermans authored 7 years ago

59)   } else if (strLayerName == "pixel") {
Stefan Schuermans add config file generator

Stefan Schuermans authored 7 years ago

60)     pLayer = &gLayerPixel;
Stefan Schuermans support decimal and hexadec...

Stefan Schuermans authored 7 years ago

61)   } else if (strLayerName == "network") {
Stefan Schuermans add config file generator

Stefan Schuermans authored 7 years ago

62)     pLayer = &gLayerNetwork;
Stefan Schuermans support decimal and hexadec...

Stefan Schuermans authored 7 years ago

63)   } else if (strLayerName == "cable") {
64)     pLayer = &gLayerCables[0];
65)   } else if (strLayerName.substr(0, 6) == "cable ") {
66)     unsigned int no = strtoul(strLayerName.substr(6).c_str(), NULL, 0);
Stefan Schuermans add config file generator

Stefan Schuermans authored 7 years ago

67)     pLayer = &gLayerCables[no];
68)   } else if (strLayerName.substr(0, 12) == "distributor ") {
Stefan Schuermans support decimal and hexadec...

Stefan Schuermans authored 7 years ago

69)     unsigned int no = strtoul(strLayerName.substr(12).c_str(), NULL, 0);
Stefan Schuermans add config file generator

Stefan Schuermans authored 7 years ago

70)     pLayer = &gLayerDistributors[no];
Stefan Schuermans support decimal and hexadec...

Stefan Schuermans authored 7 years ago

71)   } else {
Stefan Schuermans add config file generator

Stefan Schuermans authored 7 years ago

72)     return true;
Stefan Schuermans support decimal and hexadec...

Stefan Schuermans authored 7 years ago

73)   }
Stefan Schuermans add config file generator

Stefan Schuermans authored 7 years ago

74) 
75)   // get transformation matrix
76)   dimeMatrix matrix;
77)   state->getMatrix(matrix);
78) 
79)   // get geometry data
80)   dimeArray<dimeVec3f> vertices;
81)   dimeArray<int> indices;
82)   dimeVec3f extrusionDir;
83)   dxfdouble thickness;
84)   entity->extractGeometry(vertices, indices, extrusionDir, thickness);
85) 
86)   // transform geometry data
87)   for (int i = 0; i < vertices.count(); ++i)
88)     matrix.multMatrixVec(vertices[i]);
89) 
90)   // build object from geometry data
91)   Object *pObject = new Object;
92)   for (int i = 1; i < vertices.count(); ++i) {
93)     Line *pLine = new Line(Point(vertices[i - 1].x, vertices[i - 1].y),
94)                            Point(vertices[i].x, vertices[i].y));
95)     if (pLine->length() >= EPSILON) // ignore dots
96)       pObject->add(pLine);
97)     else {
Stefan Schuermans tidy output

Stefan Schuermans authored 7 years ago

98)       std::cerr << "ignoring dot at " << pLine->mStart.mX << ","
Stefan Schuermans add config file generator

Stefan Schuermans authored 7 years ago

99)                 << pLine->mStart.mY << std::endl;
100)       delete pLine;
101)     }
102)   }
103) 
104)   // build object into layer
105)   pLayer->build(pObject);
106) 
107)   return true;
108) }
109) 
110) /**
111)  * @brief create a chain
112)  * @param[in] chain chain to create
113)  * @param[in] pObjCable cable to first pixel
114)  * @return 0 on success, -1 on error
115)  */
116) int createChain(Chain &chain, const Object *pObjCable)
117) {
118)   // add all pixels
119)   const Object *pObjPixel = NULL;
120)   while (true) {
121) 
122)     // find pixels connected to cable
123)     std::vector<Layer::Intersection> intersectsPixels;
124)     gLayerPixel.getIntersections(pObjCable, intersectsPixels);
125) 
126)     // remove last pixel from results
127)     std::vector<Layer::Intersection>::iterator itPixel;
128)     for (itPixel = intersectsPixels.begin();
129)          itPixel != intersectsPixels.end(); ++itPixel) {
130)       if (itPixel->pObj == pObjPixel) {
131)         itPixel = intersectsPixels.erase(itPixel);
132)         if (itPixel == intersectsPixels.end())
133)           break;
134)       }
135)     }
136) 
137)     // end of chain
138)     if (intersectsPixels.size() < 1)
139)       return 0;
140) 
141)     // more than one next pixel
142)     if (intersectsPixels.size() > 1) {
143)       std::cerr << "pixel cable connects multiple pixels ("
144)                 << intersectsPixels[0].pt.mX << ","
145)                 << intersectsPixels[0].pt.mY << ")" << std::endl;
146)       return -1;
147)     }
148) 
149)     // pixel found
150)     pObjPixel = intersectsPixels[0].pObj;
151) 
152)     // add pixel to chain
153)     chain.mPixels.push_back(Pixel(pObjPixel));
154) 
155)     // find cables connected to pixel
156)     std::vector<Layer::Intersection> intersectsCables;
157)     gLayerCable.getIntersections(pObjPixel, intersectsCables);
158) 
159)     // remove last cable from results
160)     std::vector<Layer::Intersection>::iterator itCable;
161)     for (itCable = intersectsCables.begin();
162)          itCable != intersectsCables.end(); ++itCable) {
163)       if (itCable->pObj == pObjCable) {
164)         itCable = intersectsCables.erase(itCable);
165)         if (itCable == intersectsCables.end())
166)           break;
167)       }
168)     }
169) 
170)     // end of chain
171)     if (intersectsCables.size() < 1)
172)       return 0;
173) 
174)     // more than one next pixel
175)     if (intersectsCables.size() > 1) {
176)       std::cerr << "pixel connected to multiple pixel cables ("
177)                 << intersectsCables[0].pt.mX << ","
178)                 << intersectsCables[0].pt.mY << ")" << std::endl;
179)       return -1;
180)     }
181) 
182)     // next cable found
183)     pObjCable = intersectsCables[0].pObj;
184) 
185)   } // while (true)
186) }
187) 
188) /// sort helper for distributor/cables intersections
189) bool intersectsCablesSort(const Layer::Intersection& i1,
190)                           const Layer::Intersection& i2)
191) {
Stefan Schuermans code formatting

Stefan Schuermans authored 7 years ago

192)   return i1.pt.abs_sq() < i2.pt.abs_sq();
Stefan Schuermans add config file generator

Stefan Schuermans authored 7 years ago

193) }
194) 
195) /**
196)  * @brief create a distributor
197)  * @param[in] distri distributor to create
198)  * @param[in] pLayer layer containing distributor
199)  * @param[in] pixels number of pixels per chain
200)  * @return 0 on success, -1 on error
201)  */
202) int createDistri(Distri &distri, const Layer *pLayer, unsigned int pixels)
203) {
204)   // must have exactly one object
205)   if (pLayer->mObjects.size() != 1) {
206)     std::cerr << "layer of distributor " << std::hex << distri.mNo
Stefan Schuermans improve error messages

Stefan Schuermans authored 7 years ago

207)               << "contains no object or multiple objects" << std::endl;
Stefan Schuermans add config file generator

Stefan Schuermans authored 7 years ago

208)     return -1;
209)   }
210)   const Object *pObjDistri = pLayer->mObjects[0];
211) 
212)   // get location of network connection
213)   std::vector<Layer::Intersection> intersectsNet;
214)   gLayerNetwork.getIntersections(pObjDistri, intersectsNet);
215)   if (intersectsNet.size() != 1) {
216)     std::cerr << "distributor " << std::hex << distri.mNo
Stefan Schuermans improve error messages

Stefan Schuermans authored 7 years ago

217)               << "has no network connection or multiple network connections"
218)               << std::endl;
Stefan Schuermans add config file generator

Stefan Schuermans authored 7 years ago

219)     return -1;
220)   }
221)   Point ptNetwork = intersectsNet[0].pt;
222) 
223)   // get cables to pixel chains
224)   std::vector<Layer::Intersection> intersectsCables;
225)   gLayerCable.getIntersections(pObjDistri, intersectsCables);
226) 
227)   // sort cables according to distance to network
228)   std::vector<Layer::Intersection>::iterator itIntersect;
229)   for (itIntersect = intersectsCables.begin();
230)        itIntersect != intersectsCables.end(); ++itIntersect)
231)     itIntersect->pt -= ptNetwork;
232)   std::sort(intersectsCables.begin(), intersectsCables.end(),
233)             intersectsCablesSort);
234) 
235)   // create chains
236)   bool err = false;
237)   for (itIntersect = intersectsCables.begin();
238)        itIntersect != intersectsCables.end(); ++itIntersect) {
239)     distri.mChains.push_back(Chain(pixels));
240)     if (createChain(distri.mChains.back(), itIntersect->pObj) != 0)
241)       err = true;
242)   }
243) 
244)   return err ? -1 : 0;
245) }
246) 
247) /**
248)  * @brief write config file
249)  * @param[in] width width of video in pixels
250)  * @param[in] height height of video in pixels
251)  * @param[in] distris distributor objects
252)  */
253) int writeCfg(unsigned int width, unsigned int height,
254)              const std::vector<Distri> &distris,
255)              const std::string & strCfgFileName)
256) {
Stefan Schuermans code formatting

Stefan Schuermans authored 7 years ago

257)   // open output file
Stefan Schuermans add config file generator

Stefan Schuermans authored 7 years ago

258)   std::ofstream strm(strCfgFileName.c_str(), std::ios::out);
259)   if (!strm.is_open()) {
260)     std::cerr << "could not open \"" << strCfgFileName
261)               << "\" for wrinting" << std::endl;
262)     return -1;
263)   }
264) 
265)   // video size
266)   strm << "size = " << width << "," << height << std::endl
267)        << std::endl;
268) 
269)   // distributors
270)   std::vector<Distri>::const_iterator itD;
271)   for (itD = distris.begin(); itD != distris.end(); ++itD)
272)     itD->writeDistri(strm);
273)   strm << std::endl;
274) 
275)   // mappings
276)   for (itD = distris.begin(); itD != distris.end(); ++itD)
277)     itD->writeMapping(strm);
278)   strm << std::endl;
279) 
280)   // pixels
281)   for (itD = distris.begin(); itD != distris.end(); ++itD)
282)     itD->writePixels(strm);
283)   strm << std::endl;
284) 
285)   strm.close();
286)   return 0;
287) }
288) 
289) /**
290)  * @brief main program
291)  * @param[in] argc number of parameters
292)  * @param[in] argv parameter values
293)  * @return 0 on success, -1 on error
294)  */
295) int main(int argc, char *argv[])
296) {
297)   // get parameters
298)   if (argc < 7) {
299)     std::cerr << "FlexiPix config file generator "
300)               << FLPCG_VER_MAJ << "."
301)               << FLPCG_VER_MIN << "."
302)               << FLPCG_VER_REV << std::endl
303)               << "usage:" << std::endl
304)               << "  " << argv[0] << " \\" << std::endl
305)               << "    <schematic_drawing.dxf> <width> <height> \\" << std::endl
306)               << "    <chains> <pixels> <config.flp>" << std::endl;
307)     return -1;
308)   }
309)   std::string strDxfFileName = argv[1];
310)   unsigned int width = atoi(argv[2]);
311)   unsigned int height = atoi(argv[3]);
312)   unsigned int chains = atoi(argv[4]);
313)   unsigned int pixels = atoi(argv[5]);
314)   std::string strCfgFileName = argv[6];
315) 
316)   // read DXF file
317)   dimeInput in;
318)   if (!in.setFile(strDxfFileName.c_str())) {
319)     std::cerr << "error opening file \"" << strDxfFileName
320)               << "\" for reading" << std::endl;
321)     return -1;
322)   }
323)   dimeModel model;
324)   if (!model.read(&in)) {
325)     std::cerr << "DXF read error in line " << in.getFilePosition()
326)               << " of file \"" << strDxfFileName << "\""
327)               << std::endl;
328)     return -1;
329)   }
330) 
331)   // enumerate all entities
332)   model.traverseEntities(cbEntity, NULL);
333) 
334)   // merge all cable layers
335)   std::map<unsigned int, Layer>::iterator itCable;
336)   for (itCable = gLayerCables.begin();
337)        itCable != gLayerCables.end(); ++itCable)
338)   gLayerCable.merge(&itCable->second);
339)   // gLayerCables[] is now empty and will not be used any more
340) 
Stefan Schuermans tidy output

Stefan Schuermans authored 7 years ago

341)   // output object count information
342)   std::cout << "object counts:" << std::endl;
343)   std::cout << "  video: " << gLayerVideo.mObjects.size() << std::endl;
344)   std::cout << "  pixel: " << gLayerPixel.mObjects.size() << std::endl;
345)   std::cout << "  cable: " << gLayerCable.mObjects.size() << std::endl;
346)   std::cout << "  network: " << gLayerNetwork.mObjects.size() << std::endl;
347)   std::cout << "  distributor:" << std::endl;
Stefan Schuermans add config file generator

Stefan Schuermans authored 7 years ago

348)   std::map<unsigned int, Layer>::const_iterator itDistri;
349)   for (itDistri = gLayerDistributors.begin();
350)        itDistri != gLayerDistributors.end(); ++itDistri)
Stefan Schuermans tidy output

Stefan Schuermans authored 7 years ago

351)     std::cout << "    " << itDistri->first << ": "
Stefan Schuermans add config file generator

Stefan Schuermans authored 7 years ago

352)               << itDistri->second.mObjects.size() << std::endl;
353) 
354)   // get origin and size of pixels in video
355)   Box boundsVideo;
356)   gLayerVideo.getBounds(boundsVideo);
357)   Point ptPixel0(boundsVideo.mBL.mX, boundsVideo.mTR.mY);
358)   Point ptPixelSz = boundsVideo.mTR - boundsVideo.mBL;
359)   ptPixelSz.mX /= (double)width;
360)   ptPixelSz.mY /= (double)height;
361)   ptPixelSz.mY *= -1;
362)   std::cout << "video bounds: "
363)             << boundsVideo.mBL.mX << "," << boundsVideo.mBL.mY
364)             << " " << boundsVideo.mTR.mX << "," << boundsVideo.mTR.mY
365)             << std::endl;
366) 
367)   // create distributors
368)   bool err = false;
369)   std::vector<Distri> distris;
370)   for (itDistri = gLayerDistributors.begin();
371)        itDistri != gLayerDistributors.end(); ++itDistri) {
372)     distris.push_back(Distri(itDistri->first, chains, pixels));
Stefan Schuermans code formatting

Stefan Schuermans authored 7 years ago

373)     if (createDistri(distris.back(), &itDistri->second, pixels) != 0) {
Stefan Schuermans add config file generator

Stefan Schuermans authored 7 years ago

374)       err = true;
Stefan Schuermans code formatting

Stefan Schuermans authored 7 years ago

375)     }