-
Notifications
You must be signed in to change notification settings - Fork 7
/
board.cc
167 lines (143 loc) · 4.63 KB
/
board.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; -*-
* (c) [email protected]. Free Software. GNU Public License v3.0 and above
*/
#include "board.h"
#include <math.h>
#include <fstream>
#include "rpt-parser.h"
Position Part::padAbsPos(const Pad &p) const {
const float a = 2 * M_PI * angle / 360.0;
return { pos.x + p.pos.x * cos(a) - p.pos.y * sin(a),
pos.y + p.pos.x * sin(a) + p.pos.y * cos(a) };
}
namespace {
// Helper class to read file from parse events.
// Collect the parts from parse events.
class PartCollector : public ParseEventReceiver {
public:
PartCollector(std::vector<const Part*> *parts,
Dimension *board_dimension,
const Board::ReadFilter &filter)
: current_part_(NULL),
collected_parts_(parts), board_dimension_(board_dimension),
is_accepting_(filter) {}
protected:
void StartBoard(float max_x, float max_y) override {
board_dimension_->w = max_x;
board_dimension_->h = max_y;
}
void StartComponent(const std::string &c) override {
in_pad_ = false;
current_part_ = new Part();
current_part_->component_name = c;
is_smd_ = false;
drill_sum_ = 0;
angle_ = 0;
}
void Value(const std::string &c) override {
current_part_->value = c;
}
void Footprint(const std::string &c) override {
current_part_->footprint = c;
}
void Layer(bool is_front) override {
current_part_->is_front_layer = is_front;
}
void IsSMD(bool smd) override {
is_smd_ = smd;
}
void Drill(float size) override {
drill_sum_ += size;
}
void EndComponent() override {
const bool looks_like_smd = is_smd_ || drill_sum_ == 0;
if (!looks_like_smd || !is_accepting_(*current_part_)) {
delete current_part_;
} else {
collected_parts_->push_back(current_part_);
}
current_part_ = NULL;
}
// Not caring about pads right now.
void StartPad(const std::string &c) override {
current_pad_.name = c;
in_pad_ = true;
}
void EndPad() override {
in_pad_ = false;
if (current_part_) {
current_part_->pads.push_back(current_pad_);
}
}
void Position(float x, float y) override {
if (in_pad_) {
current_pad_.pos.Set(x, y);
} else {
current_part_->pos.x = x;
current_part_->pos.y = y;
}
}
void Size(float w, float h) override {
if (in_pad_) {
current_pad_.size.w = w;
current_pad_.size.h = h;
// TODO:
float x, y;
x = current_pad_.pos.x - w/2;
if (x < current_part_->bounding_box.p0.x)
current_part_->bounding_box.p0.x = x;
x = current_pad_.pos.x + w/2;
if (x > current_part_->bounding_box.p1.x)
current_part_->bounding_box.p1.x = x;
y = current_pad_.pos.y - h/2;
if (y < current_part_->bounding_box.p0.y)
current_part_->bounding_box.p0.y = y;
y = current_pad_.pos.y + h/2;
if (y > current_part_->bounding_box.p1.y)
current_part_->bounding_box.p1.y = y;
}
}
void Orientation(float angle) override {
if (in_pad_)
return;
// Angle is in degrees, make that radians.
// mmh, and it looks like it turned in negative direction ? Probably part
// of the mirroring.
angle_ = -M_PI * angle / 180.0;
current_part_->angle = angle; // change to angle_ if you really want radians
}
private:
void rotateXY(float *x, float *y) {
float xnew = *x * cos(angle_) - *y * sin(angle_);
float ynew = *x * sin(angle_) + *y * cos(angle_);
*x = xnew;
*y = ynew;
}
// Current coordinate system.
float angle_;
bool is_smd_;
bool in_pad_;
float drill_sum_; // heuristic to determine smd components.
::Pad current_pad_;
std::string component_name_;
Part *current_part_;
std::vector<const Part*> *collected_parts_;
Dimension *board_dimension_;
const Board::ReadFilter is_accepting_;
};
} // namespace
Board::Board() {}
Board::~Board() {
for (const Part* part : parts_) {
delete part;
}
}
bool Board::ParseFromRpt(const std::string& filename, ReadFilter filter) {
PartCollector collector(&parts_, &board_dim_, filter);
std::ifstream in(filename);
if (!in.is_open()) {
fprintf(stderr, "Can't open %s\n", filename.c_str());
return false;
}
return RptParse(&in, &collector);
}