2013-09-18 17:55:16 +00:00
|
|
|
/*
|
|
|
|
* KiRouter - a push-and-(sometimes-)shove PCB router
|
|
|
|
*
|
|
|
|
* Copyright (C) 2013 CERN
|
|
|
|
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
2013-09-26 21:53:54 +00:00
|
|
|
*
|
2013-09-18 17:55:16 +00:00
|
|
|
* 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.
|
2013-09-26 21:53:54 +00:00
|
|
|
*
|
2013-09-18 17:55:16 +00:00
|
|
|
* 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.
|
2013-09-26 21:53:54 +00:00
|
|
|
*
|
2013-09-18 17:55:16 +00:00
|
|
|
* 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
|
|
|
|
*
|
2013-10-14 11:43:57 +00:00
|
|
|
* 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
|
2013-09-26 21:53:54 +00:00
|
|
|
* belongs/begins them.
|
2013-09-18 17:55:16 +00:00
|
|
|
*
|
2013-10-14 11:43:57 +00:00
|
|
|
* 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
|
2013-09-26 21:53:54 +00:00
|
|
|
* returned by PNS_NODE::AssembleLine and friends.
|
|
|
|
*
|
2013-10-14 11:43:57 +00:00
|
|
|
* A PNS_LINE may have a PNS_VIA attached at its and - this is used by via
|
2013-09-26 21:53:54 +00:00
|
|
|
* dragging/force propagation stuff.
|
2013-09-18 17:55:16 +00:00
|
|
|
*/
|
|
|
|
|
2013-09-26 21:53:54 +00:00
|
|
|
class PNS_LINE : public PNS_ITEM
|
2013-09-18 17:55:16 +00:00
|
|
|
{
|
|
|
|
public:
|
2013-09-26 21:53:54 +00:00
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
2013-10-14 11:43:57 +00:00
|
|
|
///> Returns a list of segments from the owning node that constitute this
|
2013-09-26 21:53:54 +00:00
|
|
|
///> 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();
|
|
|
|
}
|
|
|
|
|
2013-10-14 11:43:57 +00:00
|
|
|
///> Returns this line, but clipped to the nearest obstacle
|
2013-09-26 21:53:54 +00:00
|
|
|
///> 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 );
|
|
|
|
|
2013-10-14 11:43:57 +00:00
|
|
|
///> Calculates a line thightly wrapping a convex hull
|
2013-09-26 21:53:54 +00:00
|
|
|
///> 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;
|
|
|
|
}
|
|
|
|
}
|
2013-09-18 17:55:16 +00:00
|
|
|
|
|
|
|
private:
|
2013-09-26 21:53:54 +00:00
|
|
|
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;
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2013-09-26 21:53:54 +00:00
|
|
|
///> 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;
|
|
|
|
};
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2013-09-26 21:53:54 +00:00
|
|
|
#endif // __PNS_LINE_H
|