252 lines
6.8 KiB
C++
252 lines
6.8 KiB
C++
/*
|
|
* KiRouter - a push-and-(sometimes-)shove PCB router
|
|
*
|
|
* Copyright (C) 2013 CERN
|
|
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
|
*
|
|
* This program 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.
|
|
*
|
|
* This program 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 this program. If not, see <http://www.gnu.or/licenses/>.
|
|
*/
|
|
|
|
#ifndef __PNS_LINE_H
|
|
#define __PNS_LINE_H
|
|
|
|
#include <math/vector2d.h>
|
|
|
|
#include <geometry/seg.h>
|
|
#include <geometry/shape.h>
|
|
#include <geometry/shape_line_chain.h>
|
|
|
|
#include "direction.h"
|
|
#include "pns_item.h"
|
|
#include "pns_via.h"
|
|
|
|
class PNS_NODE;
|
|
class PNS_SEGMENT;
|
|
class PNS_VIA;
|
|
|
|
/**
|
|
* Class PNS_LINE
|
|
*
|
|
* Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,
|
|
* junctions between multiple traces or two traces different widths and combinations of these).
|
|
* PNS_LINEs are NOT stored in the model (PNS_NODE) - instead, they are assembled on-the-fly, based on
|
|
* a via/pad/segment that belongs/begins them.
|
|
*
|
|
* PNS_LINEs can be either loose (consisting of segments that do not belong to any PNS_NODE) or owned (with segments
|
|
* taken from a PNS_NODE) - these are returned by PNS_NODE::AssembleLine and friends.
|
|
*
|
|
* A PNS_LINE may have a PNS_VIA attached at its and - this is used by via dragging/force propagation stuff.
|
|
*/
|
|
|
|
class PNS_LINE : public PNS_ITEM
|
|
{
|
|
public:
|
|
typedef std::vector<PNS_SEGMENT *> LinkedSegments;
|
|
|
|
PNS_LINE ():
|
|
PNS_ITEM(LINE)
|
|
{
|
|
m_segmentRefs = NULL;
|
|
m_hasVia = false;
|
|
m_affectedRangeStart = -1;
|
|
};
|
|
|
|
PNS_LINE (int aLayer, int aWidth, const SHAPE_LINE_CHAIN& aLine) :
|
|
PNS_ITEM(LINE)
|
|
{
|
|
m_line = aLine;
|
|
m_width = aWidth;
|
|
m_segmentRefs = NULL;
|
|
m_hasVia = false;
|
|
m_affectedRangeStart = -1;
|
|
SetLayer(aLayer);
|
|
|
|
}
|
|
|
|
PNS_LINE(const PNS_LINE& aOther) :
|
|
PNS_ITEM(aOther),
|
|
m_line(aOther.m_line),
|
|
m_width(aOther.m_width)
|
|
{
|
|
m_net = aOther.m_net;
|
|
m_movable = aOther.m_movable;
|
|
m_world = aOther.m_world;
|
|
m_layers = aOther.m_layers;
|
|
m_segmentRefs = NULL;
|
|
m_via = aOther.m_via;
|
|
m_hasVia = aOther.m_hasVia;
|
|
m_affectedRangeStart = -1;
|
|
}
|
|
|
|
/**
|
|
* Constructor
|
|
* copies properties (net, layers from a base line), and replaces the shape
|
|
* by aLine
|
|
**/
|
|
PNS_LINE(const PNS_LINE& aBase, const SHAPE_LINE_CHAIN& aLine) :
|
|
PNS_ITEM(aBase),
|
|
m_line(aLine),
|
|
m_width(aBase.m_width)
|
|
{
|
|
m_net = aBase.m_net;
|
|
m_layers = aBase.m_layers;
|
|
m_segmentRefs = NULL;
|
|
m_hasVia = false;
|
|
m_affectedRangeStart = -1;
|
|
}
|
|
|
|
~PNS_LINE ()
|
|
{
|
|
if(m_segmentRefs)
|
|
delete m_segmentRefs;
|
|
};
|
|
|
|
virtual PNS_LINE *Clone() const ;
|
|
|
|
///> clones the line without cloning the shape (just the properties - net, width, layers, etc.)
|
|
PNS_LINE *CloneProperties() const ;
|
|
|
|
int GetLayer() const { return GetLayers().Start(); }
|
|
|
|
///> Geometry accessors
|
|
void SetShape(const SHAPE_LINE_CHAIN& aLine) { m_line = aLine; }
|
|
const SHAPE* GetShape() const { return &m_line; }
|
|
SHAPE_LINE_CHAIN& GetLine() { return m_line; }
|
|
const SHAPE_LINE_CHAIN& GetCLine() const { return m_line; }
|
|
|
|
///> Width accessors
|
|
void SetWidth( int aWidth ) { m_width = aWidth; }
|
|
int GetWidth () const { return m_width; }
|
|
|
|
///> Links a segment from a PNS_NODE to this line, making it owned by the node
|
|
void LinkSegment(PNS_SEGMENT *aSeg)
|
|
{
|
|
if(!m_segmentRefs)
|
|
m_segmentRefs = new std::vector<PNS_SEGMENT *> ();
|
|
m_segmentRefs->push_back(aSeg);
|
|
}
|
|
|
|
///> Returns a list of segments from the owning node that constitute this line (or NULL if
|
|
///> the line is loose)
|
|
LinkedSegments* GetLinkedSegments()
|
|
{
|
|
return m_segmentRefs;
|
|
}
|
|
|
|
bool ContainsSegment (PNS_SEGMENT *aSeg) const
|
|
{
|
|
if (!m_segmentRefs)
|
|
return false;
|
|
|
|
return std::find( m_segmentRefs->begin(), m_segmentRefs->end(), aSeg) != m_segmentRefs->end();
|
|
}
|
|
|
|
///> Returns this line, but clipped to the nearest obstacle along, to avoid collision.
|
|
const PNS_LINE ClipToNearestObstacle( PNS_NODE *aNode ) const;
|
|
|
|
///> DEPRECATED optimization functions (moved to PNS_OPTIMIZER)
|
|
bool MergeObtuseSegments();
|
|
bool MergeSegments();
|
|
|
|
///> Returns the number of corners of angles specified by mask aAngles.
|
|
int CountCorners(int aAngles);
|
|
|
|
|
|
///> Calculates a line thightly wrapping a convex hull of an obstacle object (aObstacle).
|
|
///> aPrePath = path from origin to the obstacle
|
|
///> aWalkaroundPath = path around the obstacle
|
|
///> aPostPath = past from obstacle till the end
|
|
///> aCW = whether to walkaround in clockwise or counter-clockwise direction.
|
|
void NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
|
|
SHAPE_LINE_CHAIN& aPrePath,
|
|
SHAPE_LINE_CHAIN& aWalkaroundPath,
|
|
SHAPE_LINE_CHAIN& aPostPath,
|
|
bool aCw ) const;
|
|
|
|
void NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
|
|
SHAPE_LINE_CHAIN& aPath,
|
|
bool aCw ) const;
|
|
|
|
|
|
bool Walkaround(SHAPE_LINE_CHAIN obstacle, SHAPE_LINE_CHAIN &pre, SHAPE_LINE_CHAIN &walk, SHAPE_LINE_CHAIN &post, bool cw) const;
|
|
|
|
void Walkaround( const SHAPE_LINE_CHAIN& aObstacle,
|
|
SHAPE_LINE_CHAIN& aPath,
|
|
bool aCw ) const;
|
|
|
|
|
|
bool Is45Degree();
|
|
|
|
///> Prints out all linked segments
|
|
void ShowLinks();
|
|
|
|
bool EndsWithVia() const { return m_hasVia; }
|
|
|
|
void AppendVia ( const PNS_VIA &aVia ) {
|
|
m_hasVia = true;
|
|
m_via = aVia;
|
|
m_via.SetNet ( m_net ) ;
|
|
}
|
|
|
|
void RemoveVia() { m_hasVia = false; }
|
|
const PNS_VIA& GetVia() const { return m_via; }
|
|
|
|
void SetAffectedRange ( int aStart, int aEnd )
|
|
{
|
|
m_affectedRangeStart = aStart;
|
|
m_affectedRangeEnd = aEnd;
|
|
}
|
|
|
|
void ClearAffectedRange ( )
|
|
{
|
|
m_affectedRangeStart = -1;
|
|
}
|
|
|
|
bool GetAffectedRange ( int& aStart, int& aEnd )
|
|
{
|
|
if(m_affectedRangeStart >= 0)
|
|
{
|
|
aStart = m_affectedRangeStart;
|
|
aEnd = m_affectedRangeEnd;
|
|
return true;
|
|
} else {
|
|
aStart = 0;
|
|
aEnd = m_line.PointCount();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private:
|
|
bool onEdge(const SHAPE_LINE_CHAIN &obstacle, VECTOR2I p, int& ei, bool& is_vertex) const;
|
|
bool walkScan(const SHAPE_LINE_CHAIN &line, const SHAPE_LINE_CHAIN &obstacle, bool reverse, VECTOR2I &ip, int& index_o, int& index_l, bool& is_vertex) const;
|
|
|
|
///> List of semgments in a PNS_NODE (PNS_ITEM::m_owner) that constitute this line.
|
|
LinkedSegments* m_segmentRefs;
|
|
|
|
///> Shape of the line
|
|
SHAPE_LINE_CHAIN m_line;
|
|
|
|
int m_width;
|
|
///> Via at the end and a flag indicating if it's enabled.
|
|
PNS_VIA m_via;
|
|
bool m_hasVia;
|
|
|
|
int m_affectedRangeStart;
|
|
int m_affectedRangeEnd;
|
|
};
|
|
|
|
|
|
#endif // __PNS_LINE_H
|
|
|