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;
|
support decimal and hexadec...
Stefan Schuermans authored 7 years ago
|
57) if (strLayerName == "video") {
|
add config file generator
Stefan Schuermans authored 7 years ago
|
58) pLayer = &gLayerVideo;
|
support decimal and hexadec...
Stefan Schuermans authored 7 years ago
|
59) } else if (strLayerName == "pixel") {
|
add config file generator
Stefan Schuermans authored 7 years ago
|
60) pLayer = &gLayerPixel;
|
support decimal and hexadec...
Stefan Schuermans authored 7 years ago
|
61) } else if (strLayerName == "network") {
|
add config file generator
Stefan Schuermans authored 7 years ago
|
62) pLayer = &gLayerNetwork;
|
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);
|
add config file generator
Stefan Schuermans authored 7 years ago
|
67) pLayer = &gLayerCables[no];
68) } else if (strLayerName.substr(0, 12) == "distributor ") {
|
support decimal and hexadec...
Stefan Schuermans authored 7 years ago
|
69) unsigned int no = strtoul(strLayerName.substr(12).c_str(), NULL, 0);
|
add config file generator
Stefan Schuermans authored 7 years ago
|
70) pLayer = &gLayerDistributors[no];
|
support decimal and hexadec...
Stefan Schuermans authored 7 years ago
|
71) } else {
|
add config file generator
Stefan Schuermans authored 7 years ago
|
72) return true;
|
support decimal and hexadec...
Stefan Schuermans authored 7 years ago
|
73) }
|
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 {
|
tidy output
Stefan Schuermans authored 7 years ago
|
98) std::cerr << "ignoring dot at " << pLine->mStart.mX << ","
|
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) {
|
code formatting
Stefan Schuermans authored 7 years ago
|
192) return i1.pt.abs_sq() < i2.pt.abs_sq();
|
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
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) {
|
code formatting
Stefan Schuermans authored 7 years ago
|
256) // open output file
|
add config file generator
Stefan Schuermans authored 7 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)
|
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;
|
add config file generator
Stefan Schuermans authored 7 years ago
|
347) std::map<unsigned int, Layer>::const_iterator itDistri;
348) for (itDistri = gLayerDistributors.begin();
349) itDistri != gLayerDistributors.end(); ++itDistri)
|
tidy output
Stefan Schuermans authored 7 years ago
|
350) std::cout << " " << itDistri->first << ": "
|
add config file generator
Stefan Schuermans authored 7 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));
|
code formatting
Stefan Schuermans authored 7 years ago
|
372) if (createDistri(distris.back(), &itDistri->second, pixels) != 0) {
|
add config file generator
Stefan Schuermans authored 7 years ago
|
373) err = true;
|
code formatting
Stefan Schuermans authored 7 years ago
|
374) }
|