mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-03 17:34:12 +02:00
84cda1f0b0
Reported on #1178: with "route": "avoid", two contacts one above the other, wired bottom terminal to top terminal 30 px apart or closer, got a five-segment loop (at 20 px: v 80, h -20, v -140, h 20, v 80) that ran down through the lower contact and back up past the upper one. The cause was exitPoint(): it walked out of a terminal until clear of every obstacle, so with another symbol in front it walked through that symbol, and the search then had to come back. The same walk made a wire between two symbols inside a frame (a cabinet drawn as one element) leave through the frame's side, go round, and cross back in. The router now knows each terminal's own symbol (Request::start_symbol, end_symbol; applyRoute() fills them): - two terminals facing each other on one line with nothing between them are joined straight, however close; - the exit walks through the margin around other symbols but never through one; a terminal pointing straight into another symbol gets "no-route" instead of a route through it; - an obstacle drawn around either end's own symbol is left out. Without the symbols (the old Request), routes are as before. Rerouting every wire of four shipped examples (perceuse, affuteuse_250h, Polonez, industrial; 1331 wires): master routes 121 of them through another symbol, this none (10 pass through a second symbol lying exactly on an end symbol's rectangle, which no route can avoid). 99 wires that master routed through a symbol now get "no-route" and keep their path. The 1232 wires both route are 6 % shorter in total (436,144 -> 410,608 units) with 11 % fewer bends (2256 -> 2010). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
84 lines
2.9 KiB
C++
84 lines
2.9 KiB
C++
/*
|
|
Copyright 2006-2026 The QElectroTech Team
|
|
This file is part of QElectroTech.
|
|
|
|
QElectroTech 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 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
#ifndef CONDUCTORROUTER_H
|
|
#define CONDUCTORROUTER_H
|
|
|
|
#include <QList>
|
|
#include <QPointF>
|
|
#include <QRectF>
|
|
#include <QString>
|
|
#include <QVector>
|
|
|
|
/**
|
|
@brief The ConductorRouter namespace
|
|
Finds a path for a conductor that goes around obstacles -- the bounding
|
|
rectangles of the symbols on the folio -- instead of the default two or
|
|
three straight segments, which run through whatever lies between the two
|
|
terminals. Kept free of any QGraphicsItem so the geometry can be tested
|
|
on its own.
|
|
|
|
The path is made of horizontal and vertical segments only, like every
|
|
conductor. It leaves each terminal in the terminal's own direction,
|
|
runs on the folio grid, and is the cheapest one found by a search that
|
|
charges for length, for every bend, and for running along or crossing
|
|
the wires already drawn.
|
|
*/
|
|
namespace ConductorRouter
|
|
{
|
|
///The direction a terminal points, outward from its symbol.
|
|
///Same order as Qet::Orientation.
|
|
enum class Direction { North, East, South, West };
|
|
|
|
struct Request
|
|
{
|
|
QPointF start; ///< the first terminal's docking point
|
|
Direction start_direction = Direction::North;
|
|
QPointF end; ///< the second terminal's docking point
|
|
Direction end_direction = Direction::North;
|
|
///Areas no segment may cross. A margin is added to each.
|
|
QList<QRectF> obstacles;
|
|
///Each terminal's own symbol, when known, as it appears in
|
|
///obstacles. A route steps out of it first and never walks
|
|
///through another symbol to get out; an obstacle drawn around
|
|
///it (a cabinet made as one element) is left out.
|
|
QRectF start_symbol;
|
|
QRectF end_symbol;
|
|
///The other wires on the folio, each as its list of points.
|
|
///Running along one or crossing one costs extra.
|
|
QList<QVector<QPointF>> wires;
|
|
///The route stays inside this, when it is valid (the folio).
|
|
QRectF bounds;
|
|
qreal grid = 10.0;
|
|
///Added around each obstacle, so a route keeps clear of it
|
|
qreal margin = 5.0;
|
|
};
|
|
|
|
struct Result
|
|
{
|
|
///From start to end, both included; empty if none was found
|
|
QList<QPointF> points;
|
|
///Why there is no route, when points is empty
|
|
QString error;
|
|
};
|
|
|
|
Result route(const Request &request);
|
|
}
|
|
|
|
#endif // CONDUCTORROUTER_H
|