#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cmath>
#include <memory>
#include <algorithm>
// Gerber formatındaki veri yapıları
struct Point {
double x, y;
Point(double _x = 0, double _y = 0) : x(_x), y(_y) {}
};
struct GerberAperture {
int code;
std::string type;
double diameter;
};
struct GerberCommand {
char type;
std::vector<Point> points;
int aperture;
};
// Gerber parser sınıfı
class GerberParser {
private:
std::vector<GerberAperture> apertures;
std::vector<GerberCommand> commands;
Point currentPosition;
int currentAperture;
bool isRelative;
public:
GerberParser() : currentPosition(0, 0), currentAperture(0), isRelative(false) {}
bool parse(const std::string& filename) {
std::ifstream file(filename);
if (!file.is_open()) {
std::cerr << "Gerber dosyasını açma hatası: " << filename << std::endl;
return false;
}
std::string line;
while (std::getline(file, line)) {
parseLine(line);
}
return true;
}
void parseLine(const std::string& line) {
// Gerber satırlarını işle
// Bu kısım gerçek bir parserde daha kapsamlı olacaktır
if (line.find("%ADD") != std::string::npos) {
parseAperture(line);
} else if (line.find("D01") != std::string::npos) {
// Çizme komutu (Exposure On)
parseDrawCommand(line);
} else if (line.find("D02") != std::string::npos) {
// Hareket komutu (Exposure Off)
parseMoveCommand(line);
} else if (line.find("D03") != std::string::npos) {
// Flash komutu
parseFlashCommand(line);
} else if (line.find("G01") != std::string::npos) {
// Lineer interpolasyon
isRelative = false;
} else if (line.find("G91") != std::string::npos) {
// Göreceli koordinatlar
isRelative = true;
}
}
void parseAperture(const std::string& line) {
// Aperture tanımlama satırını ayrıştır
// Örnek: %ADD10C,0.01*%
GerberAperture aperture;
size_t codeStart = line.find("D") + 1;
size_t codeEnd = line.find("C", codeStart);
aperture.code = std::stoi(line.substr(codeStart, codeEnd - codeStart));
size_t diameterStart = line.find(",") + 1;
size_t diameterEnd = line.find("*");
aperture.diameter = std::stod(line.substr(diameterStart, diameterEnd - diameterStart));
aperture.type = "C"; // Yuvarlak aperture
apertures.push_back(aperture);
}
void parseDrawCommand(const std::string& line) {
// Çizme komutu
GerberCommand cmd;
cmd.type = 'D';
cmd.aperture = currentAperture;
// X ve Y koordinatlarını bul
double x = currentPosition.x;
double y = currentPosition.y;
size_t xPos = line.find("X");
size_t yPos = line.find("Y");
if (xPos != std::string::npos) {
size_t nextChar = line.find_first_of("YD*", xPos + 1);
x = std::stod(line.substr(xPos + 1, nextChar - xPos - 1)) / 1000.0; // mm cinsinden
}
if (yPos != std::string::npos) {
size_t nextChar = line.find_first_of("XD*", yPos + 1);
y = std::stod(line.substr(yPos + 1, nextChar - yPos - 1)) / 1000.0; // mm cinsinden
}
if (isRelative) {
x += currentPosition.x;
y += currentPosition.y;
}
cmd.points.push_back(currentPosition);
cmd.points.push_back(Point(x, y));
currentPosition = Point(x, y);
commands.push_back(cmd);
}
void parseMoveCommand(const std::string& line) {
// Hareket komutu
double x = currentPosition.x;
double y = currentPosition.y;
size_t xPos = line.find("X");
size_t yPos = line.find("Y");
if (xPos != std::string::npos) {
size_t nextChar = line.find_first_of("YD*", xPos + 1);
x = std::stod(line.substr(xPos + 1, nextChar - xPos - 1)) / 1000.0;
}
if (yPos != std::string::npos) {
size_t nextChar = line.find_first_of("XD*", yPos + 1);
y = std::stod(line.substr(yPos + 1, nextChar - yPos - 1)) / 1000.0;
}
if (isRelative) {
x += currentPosition.x;
y += currentPosition.y;
}
currentPosition = Point(x, y);
}
void parseFlashCommand(const std::string& line) {
// Flash komutu (pad yerleştirme)
GerberCommand cmd;
cmd.type = 'F';
cmd.aperture = currentAperture;
double x = currentPosition.x;
double y = currentPosition.y;
size_t xPos = line.find("X");
size_t yPos = line.find("Y");
if (xPos != std::string::npos) {
size_t nextChar = line.find_first_of("YD*", xPos + 1);
x = std::stod(line.substr(xPos + 1, nextChar - xPos - 1)) / 1000.0;
}
if (yPos != std::string::npos) {
size_t nextChar = line.find_first_of("XD*", yPos + 1);
y = std::stod(line.substr(yPos + 1, nextChar - yPos - 1)) / 1000.0;
}
if (isRelative) {
x += currentPosition.x;
y += currentPosition.y;
}
cmd.points.push_back(Point(x, y));
currentPosition = Point(x, y);
commands.push_back(cmd);
}
const std::vector<GerberCommand>& getCommands() const {
return commands;
}
double getApertureDiameter(int code) const {
for (const auto& aperture : apertures) {
if (aperture.code == code) {
return aperture.diameter;
}
}
return 0.0;
}
};
// İzolasyon yollarını oluşturan sınıf
class IsolationMillingGenerator {
private:
double toolDiameter;
double cutDepth;
double safeHeight;
double feedRate;
double plungeRate;
double offset;
public:
IsolationMillingGenerator(double _toolDiameter, double _cutDepth, double _safeHeight,
double _feedRate, double _plungeRate, double _offset)
: toolDiameter(_toolDiameter), cutDepth(_cutDepth), safeHeight(_safeHeight),
feedRate(_feedRate), plungeRate(_plungeRate), offset(_offset) {}
std::vector<std::string> generateGCode(const GerberParser& gerber) {
std::vector<std::string> gcode;
// G-code başlangıç ayarları
gcode.push_back("G21 ; Metrik birimler");
gcode.push_back("G90 ; Mutlak konumlandırma");
gcode.push_back("G94 ; Dakika başına besleme hızı");
gcode.push_back(std::string("F") + std::to_string(feedRate) + " ; Besleme hızı");
gcode.push_back("G00 Z" + std::to_string(safeHeight) + " ; Güvenli yüksekliğe kaldır");
// İzolasyon frezeleme için yollar oluştur
const auto& commands = gerber.getCommands();
for (const auto& cmd : commands) {
if (cmd.type == 'D' && cmd.points.size() >= 2) {
double traceDiameter = gerber.getApertureDiameter(cmd.aperture);
double isolationWidth = traceDiameter + toolDiameter + 2 * offset;
// İzolasyon yolunu oluştur
createIsolationPath(gcode, cmd.points, isolationWidth);
} else if (cmd.type == 'F' && cmd.points.size() >= 1) {
double padDiameter = gerber.getApertureDiameter(cmd.aperture);
double isolationWidth = padDiameter + toolDiameter + 2 * offset;
// Pad çevresindeki izolasyon yolunu oluştur
createPadIsolation(gcode, cmd.points[0], isolationWidth);
}
}
// G-code bitiş ayarları
gcode.push_back("G00 Z" + std::to_string(safeHeight) + " ; Güvenli yüksekliğe kaldır");
gcode.push_back("M05 ; Spindle durdur");
gcode.push_back("M30 ; Program sonu");
return gcode;
}
private:
void createIsolationPath(std::vector<std::string>& gcode, const std::vector<Point>& points, double width) {
if (points.size() < 2) return;
// İzolasyon yolunun başlangıç noktasına git
const Point& start = points[0];
gcode.push_back("G00 X" + std::to_string(start.x) + " Y" + std::to_string(start.y) + " ; Hızlı hareket");
// Kesme derinliğine in
gcode.push_back("G01 Z" + std::to_string(-cutDepth) + " F" + std::to_string(plungeRate) + " ; Kesme derinliğine in");
// Frezeleme hızına geri dön
gcode.push_back("F" + std::to_string(feedRate));
// Trace boyunca izolasyon frezeleme
for (size_t i = 1; i < points.size(); ++i) {
const Point& p = points[i];
gcode.push_back("G01 X" + std::to_string(p.x) + " Y" + std::to_string(p.y) + " ; İzolasyon frezeleme");
}
// Çift geçiş için offset mesafesi kullanarak tekrar frezele (daha temiz izolasyon için)
if (offset > 0) {
// Offset mesafesini kullanarak yolun etrafında dolaş
// Bu kısım gerçek uygulamada daha karmaşık bir hesaplama gerektirir
// (Paralel yol hesaplama algoritmalarıyla)
}
// Güvenli yüksekliğe çık
gcode.push_back("G00 Z" + std::to_string(safeHeight) + " ; Güvenli yüksekliğe kaldır");
}
void createPadIsolation(std::vector<std::string>& gcode, const Point& center, double diameter) {
// Pad çevresinde izolasyon frezeleme
double radius = diameter / 2.0;
// Pad'in etrafına ilk noktaya git
Point firstPoint(center.x + radius, center.y);
gcode.push_back("G00 X" + std::to_string(firstPoint.x) + " Y" + std::to_string(firstPoint.y) + " ; Hızlı hareket");
// Kesme derinliğine in
gcode.push_back("G01 Z" + std::to_string(-cutDepth) + " F" + std::to_string(plungeRate) + " ; Kesme derinliğine in");
// Frezeleme hızına geri dön
gcode.push_back("F" + std::to_string(feedRate));
// Çember etrafında frezele
gcode.push_back("G02 X" + std::to_string(firstPoint.x) + " Y" + std::to_string(firstPoint.y) +
" I" + std::to_string(-radius) + " J0 ; Pad etrafında izolasyon frezeleme");
// Güvenli yüksekliğe çık
gcode.push_back("G00 Z" + std::to_string(safeHeight) + " ; Güvenli yüksekliğe kaldır");
}
};
int main(int argc, char** argv) {
if (argc < 3) {
std::cout << "Kullanım: " << argv[0] << " <gerber_dosyası> <gcode_çıktı_dosyası>" << std::endl;
std::cout << "Örnek: " << argv[0] << " devre.gbr devre.gcode" << std::endl;
return 1;
}
std::string gerberFile = argv[1];
std::string gcodeFile = argv[2];
// Gerber dosyasını analiz et
GerberParser parser;
if (!parser.parse(gerberFile)) {
std::cerr << "Gerber dosyasını ayrıştırma hatası!" << std::endl;
return 1;
}
// Kullanıcıdan parametreleri al veya varsayılan değerleri kullan
double toolDiameter = 0.1; // mm cinsinden
double cutDepth = 0.1; // mm cinsinden
double safeHeight = 1.0; // mm cinsinden
double feedRate = 120.0; // mm/dk
double plungeRate = 60.0; // mm/dk
double offset = 0.05; // mm cinsinden
// Kullanıcıdan parametreleri al (opsiyonel)
std::cout << "Freze çapı (mm) [" << toolDiameter << "]: ";
std::string input;
std::getline(std::cin, input);
if (!input.empty()) toolDiameter = std::stod(input);
std::cout << "Kesme derinliği (mm) [" << cutDepth << "]: ";
std::getline(std::cin, input);
if (!input.empty()) cutDepth = std::stod(input);
std::cout << "Güvenli yükseklik (mm) [" << safeHeight << "]: ";
std::getline(std::cin, input);
if (!input.empty()) safeHeight = std::stod(input);
std::cout << "Besleme hızı (mm/dk) [" << feedRate << "]: ";
std::getline(std::cin, input);
if (!input.empty()) feedRate = std::stod(input);
std::cout << "Dalma hızı (mm/dk) [" << plungeRate << "]: ";
std::getline(std::cin, input);
if (!input.empty()) plungeRate = std::stod(input);
std::cout << "İzolasyon offset (mm) [" << offset << "]: ";
std::getline(std::cin, input);
if (!input.empty()) offset = std::stod(input);
// G-code oluştur
IsolationMillingGenerator generator(toolDiameter, cutDepth, safeHeight, feedRate, plungeRate, offset);
std::vector<std::string> gcode = generator.generateGCode(parser);
// G-code'u dosyaya yaz
std::ofstream outFile(gcodeFile);
if (!outFile.is_open()) {
std::cerr << "G-code çıktı dosyasını açma hatası: " << gcodeFile << std::endl;
return 1;
}
for (const auto& line : gcode) {
outFile << line << std::endl;
}
std::cout << "G-code başarıyla oluşturuldu: " << gcodeFile << std::endl;
return 0;
}