/* * 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