664f0b2877943accd80ec56195b27833e3d72722
Stefan Schuermans add config file generator

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

Stefan Schuermans authored 7 years ago

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

Stefan Schuermans authored 8 years ago

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

Stefan Schuermans authored 7 years ago

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

Stefan Schuermans authored 8 years ago

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

Stefan Schuermans authored 7 years ago

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

Stefan Schuermans authored 8 years ago

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

Stefan Schuermans authored 7 years ago

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

Stefan Schuermans authored 8 years ago

373)       err = true;
Stefan Schuermans code formatting

Stefan Schuermans authored 7 years ago

374)     }