mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-13 02:32:09 +10:00
A component can report which side of the board it is mounted on, and Gerber export puts the silkscreen of a part mounted underneath on the bottom layer
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
DIYLC is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DIYLC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.core;
|
||||
|
||||
import org.diylc.common.PCBLayer;
|
||||
|
||||
/**
|
||||
* Interface for components mounted on one side of a board, such as a resistor or an IC. The side
|
||||
* says where the part sits physically; it is separate from {@link ILayeredComponent}, which drives
|
||||
* continuity, because the leads of a through-hole part connect to copper on both sides whichever
|
||||
* side the part is mounted on. Components whose copper already has a layer (traces, pads, ground
|
||||
* fills) do not implement it.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface IBoardSideComponent {
|
||||
|
||||
/**
|
||||
* @return {@link PCBLayer#_2} for the top of the board or {@link PCBLayer#_1} for the bottom,
|
||||
* never an inner layer or null
|
||||
*/
|
||||
PCBLayer getBoardSide();
|
||||
}
|
||||
@@ -16,8 +16,10 @@ import org.apache.log4j.Logger;
|
||||
|
||||
import com.bancika.gerberwriter.DataLayer;
|
||||
|
||||
import org.diylc.common.PCBLayer;
|
||||
import org.diylc.core.ComponentState;
|
||||
import org.diylc.core.IBoard;
|
||||
import org.diylc.core.IBoardSideComponent;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.IView;
|
||||
import org.diylc.core.Project;
|
||||
@@ -158,8 +160,14 @@ public class GerberExporter {
|
||||
gerberComponentCustom.draw(g2d, ComponentState.NORMAL, outlineMode, currentProject, g2d, g2d);
|
||||
} else if (gerberComponent instanceof IGerberComponentSimple) {
|
||||
IGerberComponentSimple gerberComponentSimple = (IGerberComponentSimple) gerberComponent;
|
||||
g2d.startGerberOutput(gerberComponentSimple.getGerberLayer(),
|
||||
gerberComponentSimple.getGerberFunction(), gerberComponentSimple.isGerberNegative());
|
||||
GerberLayer layer = gerberComponentSimple.getGerberLayer();
|
||||
// components emit their top-side layer; a part mounted underneath goes to the bottom one
|
||||
if (c instanceof IBoardSideComponent
|
||||
&& ((IBoardSideComponent) c).getBoardSide() == PCBLayer._1) {
|
||||
layer = layer.flip();
|
||||
}
|
||||
g2d.startGerberOutput(layer, gerberComponentSimple.getGerberFunction(),
|
||||
gerberComponentSimple.isGerberNegative());
|
||||
c.draw(g2d, ComponentState.NORMAL, outlineMode, currentProject, g2d);
|
||||
g2d.stopGerberOutput();
|
||||
}
|
||||
|
||||
@@ -29,7 +29,9 @@ import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import org.diylc.common.PCBLayer;
|
||||
import org.diylc.core.ComponentState;
|
||||
import org.diylc.core.IBoardSideComponent;
|
||||
import org.diylc.core.IDrawingObserver;
|
||||
import org.diylc.core.Project;
|
||||
import org.diylc.testcomponents.MockDIYComponent;
|
||||
@@ -51,6 +53,27 @@ public class GerberExporterTest {
|
||||
assertEquals(EnumSet.of(GerberLayer.CopperBot), EnumSet.copyOf(g2d.getLayerMap().keySet()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTopSideComponentKeepsItsLayer() {
|
||||
GerberG2DWrapper g2d = draw(new SidedGerberComponent(PCBLayer._2));
|
||||
|
||||
assertEquals(EnumSet.of(GerberLayer.SilkscreenTop), EnumSet.copyOf(g2d.getLayerMap().keySet()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBottomSideComponentGoesToTheOtherSide() {
|
||||
GerberG2DWrapper g2d = draw(new SidedGerberComponent(PCBLayer._1));
|
||||
|
||||
assertEquals(EnumSet.of(GerberLayer.SilkscreenBot), EnumSet.copyOf(g2d.getLayerMap().keySet()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComponentWithoutSideStaysOnTop() {
|
||||
GerberG2DWrapper g2d = draw(new SidedGerberComponent(null));
|
||||
|
||||
assertEquals(EnumSet.of(GerberLayer.SilkscreenTop), EnumSet.copyOf(g2d.getLayerMap().keySet()));
|
||||
}
|
||||
|
||||
private static GerberG2DWrapper draw(SimpleGerberComponent component) {
|
||||
BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D graphics = img.createGraphics();
|
||||
@@ -85,4 +108,22 @@ public class GerberExporterTest {
|
||||
g2d.fill(new Rectangle2D.Double(10, 10, 20, 20));
|
||||
}
|
||||
}
|
||||
|
||||
public static class SidedGerberComponent extends SimpleGerberComponent
|
||||
implements IBoardSideComponent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private PCBLayer side;
|
||||
|
||||
public SidedGerberComponent(PCBLayer side) {
|
||||
super(null);
|
||||
this.side = side;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PCBLayer getBoardSide() {
|
||||
return side;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user