PCB gerber kodlarindan kazima dosyasina ait G kodlarini uretecek programi yazmak

Mikro Step

Kıdemli Üye
Katılım
25 Eylül 2022
Mesajlar
6,580
Yillar once bir asamaya kadar getirip ardindan havlu attigim bir proje halen icimde uhte kaldi.
Bu yakinlarda baslamam pek mumkun degil fakat onumuzdeki yil belki.

Fikir yurutme acisindan bu basligi actim.

PCB cizim programinda asagidaki cizimi yapmis olalim.
1740573314347.png


Gerber kodlarini urettigimizde CAM dosyasindaki verilerle yeniden minimal bir cizim (cizgi kalinligi 1 pixel, delik capi 1 pixel gibi) yapilacak olursa asagidaki cizim ortaya cikar.

1740573403709.png

Burada yol kalinligi ayrica ornegin 0.5mm gibi verilir. Keza yollarin uclarindaki padlerin dis olculeri de parametre olarak cap ve sekil (kare, yuvarlak, ortogon) olarak verilir.
Delik capi gerber kodda degil delik capi dosyasinda bulunur. Gerber kodlar arasinda dogrularin baslangic ve bitis koordinatlari bulunur.

Simdi yukaridaki veriden yola cikarak asagidaki kazima rotasini nasil belirleyecegiz uzerine kafa yoralim. Kazima ucu siyah cizgilerle belirlenen yolu izlediginde kirmizi yol kalacak.

1740573650865.png


Siyah cizginin kirmizi yoldan ne kadar uzakta olacagi kazima ucunun capi (d) ile ilgili bir parametredir.
O halde bu uzakliga a diyelim. Yani a=d/2 olacaktir.

1740574063146.png

Simdi elimizdeki verilerden asagidaki on hazirlik verisini elde ederiz. Bu verilerle kazima yaparsak olmaz.

Neden olmaz?

Uclari birlesmemis kazima rotalari var. Bunlar kisa devrelere neden olur.
Birbirini kesisip devam etmis yollar var. Bunlar acik devrelere neden olabilir yada yollari fazla inceltecek kesiklere neden olur.
1740574746846.png

Yesil kazima yollarinin baslangic ve bitis koordinatlari normal denkleminden kolayca hesaplanir.
Yesil kazima yollari siyah yola paralel ve a kadar uzakliktadir.

Ayni sekilde daire kazima yari capi = pad yari capi + a dan hesaplanir.

Simdi elimizde yesil yollarin tum verileri var. Fakat asagidaki sekli uretecek sekilde modifikasyon yapmamiz lazim.

1740575935615.png


Dikkat ederseniz bazi yollari kesmemiz bazilarini da uzatmamiz gerekecek.

Ben buraya kadar gelebilmis sonrasinda ilerleyememistim.

Gelen ilhamla artik cozumu kismen biliyorum.

Egimleri farkli iki dogru nerde kesisir sorusunu cozmek gerekiyor. Bu soru cozuldugunde

Asagidaki ! ve !! lerdeki sorunlar cozulmus olur.

Bir diger soru ise merkezi ve capi belli cember ile koordinatlari bilinen dogru nerde kesisir sorusunu da cozmek gerekiyor.
Bu soru da cozuldugunde !!! ile ilgili sorunlar ortadan kalkar.

!!!! ile ilgili sorunu ise simdilik nasil cozecegimi bilmiyorum. Aslinda basit bir mantik yurutme gerekiyor.

1740576011520.png


Bu durumda asagidaki kazima yoluna ulasilir.

1740575257808.png


Tabiki burada pad yada vialarin sadece daire oldugunu varsaydik. Kare vs olmasi durumunda benzer hesaplari yapmak gerekir.
 

Ekler

  • 1740575525017.png
    1740575525017.png
    8.3 KB · Görüntüleme: 12
  • 1740574883229.png
    1740574883229.png
    5.9 KB · Görüntüleme: 13
Son düzenleme:
Bu tip yazilimlari kendin yaptiginda konuya tam anlamiyla hakim olur istedigin gelismeleri yapabilirsin.
Makineyle birlikte verdigin program da senin markanla cikmis olur.

Oteki turlu Ahmet'in Mehmet'in yazdigiyla yetinirsin.

Ayni durum 3D dilimleme de de sozkonusu.

Mesela aklimdaki sey yapildimi bilmiyorum. Millet erimis plastik, cama ya da isitici tablaya yapismiyor kalkma yapiyor konusundan sikayetci. Yapistiriciyla falan care ariyorlar.

Dilimleme programini kendim yazabiliyor olsam cizimi inceletip tabladaki hazir acilmis vida deliklerinden suraya suraya vida tak dedirtirim. Sonra vidalarin dislerini ve etrafini plastikle iyice sivar en alt yuzeyi saseye sabitlerim. Sonra da ustune normal baskiyi yaptiririm. Bu sayede temel vidalarla saseye sabit oldugundan kalkma sorunu yasanmaz. Bu ve benzeri gelismeleri sen yaparsin artik sen milletin yaptiklarini degil millet senin yaptiklarini takip etmeye baslar.
 
Son düzenleme:
Ticari olarak düşünüyorsan anlarım.
Ancak hobi olarak yada şurada da şöyle bişey olsa iyi olur mantığına biraz ters.
Bazı şeyler keşfedilmişse yamuk yumuk ta olsa iş görüyorsa yetinirim asli işim onu üretmek değilse.
Zaten verdiğim programlar da açık kaynak kodlu.
Şahıslarla irtibatlanıp şöyle şöyle olsa daha iyi olur denildiğinde yeni versiyona ekliyorlar.
Kısacası Public-free olan da kusur aranmaz. (beleş atın dişine bakılmaz)
 
Olmaz oyle sey. Borunu otturmek istiyorsan kendin yapacaksin.

O zaman neden sifirdan devre tasarliyoruz?. Birilerinin devrelerini alip kullanalim yada modifiye edelim yada sahislarla irtibata gecelim istedikleriizi yeni versiyona eklesinler.
 
Bende cnc makinemi bitirebilirsem aynı sorunlarla uğraşacağım.
Para ve tembellik sorunum var.
y1=m1*x1+a
y2=m2*x2+b

y1=y2 eşit olduğunda keşisim noktaları bulunur

cember ile doğrunun kesişim noktalarıda benzer şekilde bulunulur.

cember denklemini yazmaya gerek yok.

Aslında iki noktanın bitiş yerleri belli.
iki nokta arasına düz çizgi çizmek daha kolay.
İki nokta arasında geçen doğru denklemi yazılır.

m=(y2-y1)/(x2-x1)
y1=m*x+a
 
Cember denklemine gerek var. Cunku yolun altindan ve ustunden gececek hesaplanan yollar cember uzerinde nerede kesisecek onun hesaplanmasi sart.
Aksi halde kazima cemberin icine dogru devam eder. (Asagidaki cizimde !!! olarak gosterilen kisimlarin traslanmasi gerekiyor)

Madem meraklisin asagidaki cizimde !!!! olarak gosterilen yay parcalarinin iptaline iliskin algoritmaya kafa yorabilirmisin?

Iki dogru parcasi cemberi kesiyor. Iki dogru arasida kalan yay parcasinin kazinmamasi gerekiyor.



1740655265095.png
 
Cember denklemine gerek var. Cunku yolun altindan ve ustunden gececek hesaplanan yollar cember uzerinde nerede kesisecek onun hesaplanmasi sart.
Aksi halde kazima cemberin icine dogru devam eder. (Asagidaki cizimde !!! olarak gosterilen kisimlarin traslanmasi gerekiyor)

Madem meraklisin asagidaki cizimde !!!! olarak gosterilen yay parcalarinin iptaline iliskin algoritmaya kafa yorabilirmisin?

Iki dogru parcasi cemberi kesiyor. Iki dogru arasida kalan yay parcasinin kazinmamasi gerekiyor.



40564 eklentisine bak

Desmosda yarısını yaptım ama çember ile yol arasında ufak boşluk kalıyor. Yuvarladığı için olabilir.

yol y eksenine paralel olunca siliniyor.

Delphi ile yazsam o zorunu çözerdim.

Hastalığımdan dolayı uzun kod yazamıyorum.

Çemberleri doğruları parametrik koordinat sisteminde çizersem daha kolay geliyor bana.
 
Olmaz oyle sey. Borunu otturmek istiyorsan kendin yapacaksin.

O zaman neden sifirdan devre tasarliyoruz?. Birilerinin devrelerini alip kullanalim yada modifiye edelim yada sahislarla irtibata gecelim istedikleriizi yeni versiyona eklesinler.
Devre tasarlamak başka ürün çıkarmak başka şey.
Devre tasarladığında devrenin elemanlarınıda kendin tasarlayıp üretmiyorsun sonuçta.

Eğer hayati derecede önem arzediyorsa şirket yada ülke açısından o zaman haklısındır.
Ama bireysel uğraşlarda işini hızlı görebilmek daha önemlidir.
Emsali olmayan şeyleri tabiiki yapmak zorundasındır.

Mesela adam kaşık imal etmiş ve satıyor kusurlu yada değil.
Bir güvenlik açığından bahsediyorsak Kendin yapacaksan topraktan mineral çıkarmakla başlamazsan güvende değilsindir.
Eğer sadece metal alır kaşık yapma teknolojisi oluştururum dersende metalleri satmadıkları zaman sıkıntıya girersin.
Kaldıki görünüşte basit bir önek olmasına rağmen hiç te basit değil.
Kaşık yapacak makineyide kendin yapmakla beraber makinanın en ufak civatasını boyasını elektirik morotusunu elektirik üreten santrali/jeneratörü ve dahi enerji taşıyan kablolarını vs.. de kendin yapmak zorundasın.

Halbuki zora düşünce yapmak en kolayıdır.
O zamana kadar herşeyi olabildiğince tedarike dayalı yapmak hız ve üretim ortaya çıkarır.

Çok uzun yazdım kusura bakmayın ama başka türlüde izah edilemiyor.
 
Hocam bu benim dusturum. Seninki farkli olabilir. Yapamayacagim seyler olursa o zaman yaptiriyorum.

Bir cihaz yapiyorsam, elektronigini de mekanigini de yazilimini da kendim yapiyorum. Cunku tek basimayim, ekibim yok, cok para verip akli basinda firmalarla calisamam, az paraya da usta bozuntulari ile hic calisamam.

Bu yazilimi neden sen yapmaya calisiyorsun diye sormak yerine onca fakultenin bilgisayar mezunlarina neden boyle programlar yazmiyorsunuz diye sormak lazim.
 
Dayanamadim, programi yazmaya basladim.

Eagle ile cizilen test calismasi.

1740952298302.png


Asagidaki de CAM dosyalarindan bahse konu PCB'ye ait ham pcb verilerinin grafige dokulmesi.

1740952432032.png


Simdi sirada kontur cizgilerinin elde edilmesi var.

Asil iste burasi.
 
PCB gerber dosyadan, "isolation milling" kazıma dosyasını G-code olarak üreten program

C++:
#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;
}
 
Şu değil midir:
Kod:
// İzolasyon yollarını oluşturan sınıf
class IsolationMillingGenerator {
içinde gerekli fonksiyonlar var. hap gibi yapılmış sanki.
 
Biraz daha aşağı inince şu kısım:
C++:
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)
        }
 
iyileştirme yaptı.

C++:
void createIsolationPath(std::vector<std::string>& gcode, const std::vector<Point>& points, double width) {
    if (points.size() < 2) return;
  
    // İlk geçiş - ana izin üzerinden
    const Point& start = points[0];
    gcode.push_back("G00 X" + std::to_string(start.x) + " Y" + std::to_string(start.y) + " ; Hızlı hareket");
    gcode.push_back("G01 Z" + std::to_string(-cutDepth) + " F" + std::to_string(plungeRate) + " ; Kesme derinliğine in");
    gcode.push_back("F" + std::to_string(feedRate));
  
    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");
    }
  
    // İkinci geçiş - offset yol üzerinden
    if (offset > 0 && points.size() >= 2) {
        // Offset yolları hesapla
        std::vector<Point> offsetPath = calculateOffsetPath(points, offset);
      
        if (!offsetPath.empty()) {
            // Offset yolun başlangıcına git
            gcode.push_back("G00 Z" + std::to_string(safeHeight) + " ; Güvenli yüksekliğe kaldır");
            gcode.push_back("G00 X" + std::to_string(offsetPath[0].x) + " Y" + std::to_string(offsetPath[0].y) + " ; Offset başlangıcına git");
            gcode.push_back("G01 Z" + std::to_string(-cutDepth) + " F" + std::to_string(plungeRate) + " ; Kesme derinliğine in");
            gcode.push_back("F" + std::to_string(feedRate));
          
            // Offset yolu izle
            for (size_t i = 1; i < offsetPath.size(); ++i) {
                const Point& p = offsetPath[i];
                gcode.push_back("G01 X" + std::to_string(p.x) + " Y" + std::to_string(p.y) + " ; Offset izolasyon frezeleme");
            }
        }
    }
  
    // Güvenli yüksekliğe çık
    gcode.push_back("G00 Z" + std::to_string(safeHeight) + " ; Güvenli yüksekliğe kaldır");
}

// İz çizgisi için offset yol hesaplama
std::vector<Point> calculateOffsetPath(const std::vector<Point>& originalPath, double offsetDistance) {
    std::vector<Point> offsetPath;
    if (originalPath.size() < 2) return offsetPath;
  
    // Her segment için offset hesapla
    for (size_t i = 0; i < originalPath.size() - 1; ++i) {
        const Point& p1 = originalPath[i];
        const Point& p2 = originalPath[i + 1];
      
        // Segment yönü vektörü
        double dx = p2.x - p1.x;
        double dy = p2.y - p1.y;
      
        // Segment uzunluğu
        double length = std::sqrt(dx * dx + dy * dy);
      
        if (length < 1e-6) continue; // Çok kısa segmentleri atla
      
        // Birim vektör
        double nx = dx / length;
        double ny = dy / length;
      
        // 90 derece döndürülmüş birim normal vektör (saat yönünün tersine)
        double offsetX = -ny;
        double offsetY = nx;
      
        // Offset noktaları hesapla
        Point offsetP1(p1.x + offsetX * offsetDistance, p1.y + offsetY * offsetDistance);
        Point offsetP2(p2.x + offsetX * offsetDistance, p2.y + offsetY * offsetDistance);
      
        // İlk noktayı ekle (çift eklemeyi önlemek için)
        if (offsetPath.empty()) {
            offsetPath.push_back(offsetP1);
        }
      
        offsetPath.push_back(offsetP2);
    }
  
    // Offset yolunu köşelerde düzeltme işlemi uygula
    adjustOffsetPathCorners(offsetPath, originalPath, offsetDistance);
  
    return offsetPath;
}

// Köşelerdeki offset yolunu düzeltir (kesişim noktalarını bul)
void adjustOffsetPathCorners(std::vector<Point>& offsetPath, const std::vector<Point>& originalPath, double offsetDistance) {
    if (offsetPath.size() < 3) return;  // Düzeltme için en az 3 nokta gerekir
  
    std::vector<Point> adjustedPath;
    adjustedPath.push_back(offsetPath[0]);  // İlk noktayı ekle
  
    // Her üç ardışık noktayı kontrol et
    for (size_t i = 0; i < offsetPath.size() - 2; ++i) {
        const Point& p1 = offsetPath[i];
        const Point& p2 = offsetPath[i + 1];  // Köşe noktası
        const Point& p3 = offsetPath[i + 2];
      
        // İki segment arasındaki kesişim noktasını bul
        Point intersection;
        bool hasIntersection = findLinesIntersection(p1, p2, p2, p3, intersection);
      
        if (hasIntersection) {
            // Köşe çok keskin değilse kesişim noktasını kullan
            double distToCorner = std::sqrt(
                std::pow(intersection.x - p2.x, 2) +
                std::pow(intersection.y - p2.y, 2)
            );
          
            // Köşe yumuşatmayı kritik bir mesafeyle sınırla
            if (distToCorner < 3 * offsetDistance) {
                adjustedPath.push_back(intersection);
            } else {
                // Köşe çok keskinse orijinal noktayı kullan
                adjustedPath.push_back(p2);
            }
        } else {
            // Kesişim bulunamadıysa orijinal noktayı kullan
            adjustedPath.push_back(p2);
        }
    }
  
    // Son noktayı ekle
    adjustedPath.push_back(offsetPath.back());
  
    // Düzeltilmiş yolu orijinal offset yolu ile değiştir
    offsetPath = adjustedPath;
}

// İki çizginin kesişim noktasını bul
bool findLinesIntersection(const Point& p1, const Point& p2, const Point& p3, const Point& p4, Point& intersection) {
    // Çizgi 1: p1 -> p2
    // Çizgi 2: p3 -> p4
  
    double x1 = p1.x, y1 = p1.y;
    double x2 = p2.x, y2 = p2.y;
    double x3 = p3.x, y3 = p3.y;
    double x4 = p4.x, y4 = p4.y;
  
    double denominator = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
  
    // Çizgiler paralel veya çakışık
    if (std::abs(denominator) < 1e-6) {
        return false;
    }
  
    double ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator;
  
    // Kesişim noktasını hesapla
    intersection.x = x1 + ua * (x2 - x1);
    intersection.y = y1 + ua * (y2 - y1);
  
    return true;
}

// Düzgün bir kapalı izolasyon çevresi oluşturmak için
std::vector<Point> createClosedOffsetPath(const std::vector<Point>& originalPath, double offsetDistance, bool isClockwise) {
    // İzin kapalı olup olmadığını kontrol et
    bool isClosed = false;
    if (originalPath.size() > 2) {
        Point first = originalPath.front();
        Point last = originalPath.back();
        if (std::abs(first.x - last.x) < 1e-6 && std::abs(first.y - last.y) < 1e-6) {
            isClosed = true;
        }
    }
  
    // Eğer iz kapalıysa, özel işlem gerekiyor
    if (isClosed) {
        // Kapalı bir iz için offset hesapla
        std::vector<Point> offsetPath;
      
        // Çokgenin iç veya dış tarafına offset uygulamak için işaret ayarlama
        double sign = isClockwise ? 1.0 : -1.0;
      
        // Her köşe için offset hesapla
        for (size_t i = 0; i < originalPath.size() - 1; ++i) {
            // Önceki, şu anki ve sonraki noktalar
            size_t prevIdx = (i == 0) ? (originalPath.size() - 2) : (i - 1);
            size_t currIdx = i;
            size_t nextIdx = i + 1;
          
            const Point& prev = originalPath[prevIdx];
            const Point& curr = originalPath[currIdx];
            const Point& next = originalPath[nextIdx];
          
            // Köşedeki açıyı hesapla
            double dx1 = curr.x - prev.x;
            double dy1 = curr.y - prev.y;
            double dx2 = next.x - curr.x;
            double dy2 = next.y - curr.y;
          
            // Birim vektörler
            double len1 = std::sqrt(dx1*dx1 + dy1*dy1);
            double len2 = std::sqrt(dx2*dx2 + dy2*dy2);
          
            if (len1 < 1e-6 || len2 < 1e-6) continue;
          
            dx1 /= len1;
            dy1 /= len1;
            dx2 /= len2;
            dy2 /= len2;
          
            // Normal vektörler
            double nx1 = -dy1 * sign;
            double ny1 = dx1 * sign;
            double nx2 = -dy2 * sign;
            double ny2 = dx2 * sign;
          
            // İki segment için offset noktaları
            Point offsetPoint1(curr.x + nx1 * offsetDistance, curr.y + ny1 * offsetDistance);
            Point offsetPoint2(curr.x + nx2 * offsetDistance, curr.y + ny2 * offsetDistance);
          
            // Kesişim noktasını bul
            Point intersection;
            bool hasIntersection = findLinesIntersection(
                offsetPoint1, Point(offsetPoint1.x + dx1, offsetPoint1.y + dy1),
                offsetPoint2, Point(offsetPoint2.x - dx2, offsetPoint2.y - dy2),
                intersection
            );
          
            if (hasIntersection) {
                offsetPath.push_back(intersection);
            } else {
                // Kesişim bulunamadıysa ortalama nokta kullan
                offsetPath.push_back(Point(
                    (offsetPoint1.x + offsetPoint2.x) / 2,
                    (offsetPoint1.y + offsetPoint2.y) / 2
                ));
            }
        }
      
        // Kapalı yol için son noktayı ilk noktayla aynı yap
        if (!offsetPath.empty()) {
            offsetPath.push_back(offsetPath[0]);
        }
      
        return offsetPath;
    } else {
        // Açık bir iz için standart offset hesaplama
        return calculateOffsetPath(originalPath, offsetDistance);
    }
}

  • Ana İzolasyon Yolu Fonksiyonu:
    • Önce orijinal yol üzerinde frezeleme yapar
    • Sonra offset mesafesinde ikinci bir geçiş yapar
  • Offset Yol Hesaplama:
    • calculateOffsetPath: Her segment için 90 derece döndürülmüş normal vektör kullanarak offset noktaları oluşturur
    • Vektör matematiği kullanarak, çizginin bir tarafında paralel bir çizgi oluşturur
  • Köşe Düzeltme:
    • adjustOffsetPathCorners: Offset yolundaki keskin köşeleri düzeltir
    • Ardışık segmentlerin kesişim noktalarını bularak daha doğru bir offset yolu oluşturur
  • Kapalı Yollar İçin Özel İşlem:
    • createClosedOffsetPath: Kapalı bir izin (örneğin bir padın çevresi) etrafında offset yolu oluşturur
    • İç ve dış offset'leri destekler (saat yönünde veya tersine)
 
Son düzenleme:
1741094717749.png


Geldik zurnanin zirt dedigi delige.

PCB cizim programinda kirmizi yolun koordinatlari belli. Yol kalinligi da belli. Sari cizgilerle bu yola iki paralel yol daha cizdik. Simdi kesisen yerleri traslayip, kesismeyenleri de uzatacagiz.
 
Son düzenleme:

Forum istatistikleri

Konular
7,411
Mesajlar
125,055
Üyeler
3,012
Son üye
BenMuhsin

Son kaynaklar

Son profil mesajları

Freemont2.0 herbokolog Freemont2.0 wrote on herbokolog's profile.
nick iniz yakıyor
:D
Freemont2.0 posta Freemont2.0 wrote on posta's profile.
Merhabalar :)
az bilgili çok meraklı
Prooffy semih_s Prooffy wrote on semih_s's profile.
Merhaba, sizden DSO2C10 hakkında bilgi rica ettim. Yanıtlarsanız sevinirim...
Unal taydin Unal wrote on taydin's profile.
Timur Bey, Arduino kontrollü bir akü şarj cihazı yapmaya çalışıyorum. Aklımdaki fikri basit bir çizim olarak konu açmıştım. Özellikle sizin fikirlerinizi çok önemsiyorum.
Back
Top