Loading files
3d097a032This file is pinned to the selected release. Download the original to open it in your design tool.
// Created on: 1993-10-07
// Created by: Yves FRICAUD
// Copyright (c) 1993-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <Extrema_ExtCC2d.hxx>
#include <Extrema_ExtPC2d.hxx>
#include <Extrema_POnCurv2d.hxx>
#include <Geom2d_CartesianPoint.hxx>
#include <Geom2d_Point.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <MAT2d_Connexion.hxx>
#include <NCollection_Array2.hxx>
#include <MAT2d_MiniPath.hxx>
#include <Standard_NotImplemented.hxx>
#include <Geom2d_Geometry.hxx>
#include <NCollection_Sequence.hxx>
#include <Standard_Integer.hxx>
//=================================================================================================
MAT2d_MiniPath::MAT2d_MiniPath()
: theDirection(1.0),
indStart(0)
{
}
//============================================================================
// function : Perform
// purpose : Calcul du chemin reliant les differents elements de <aFigure>.
// le chemin part de la ligne <IndStart>.
// <Sense> = True les lignes sont orientes dans le sens trigo.
//============================================================================
void MAT2d_MiniPath::Perform(
const NCollection_Sequence<NCollection_Sequence<occ::handle<Geom2d_Geometry>>>& Figure,
const int IndStart,
const bool Sense)
{
int i, j;
int NbLines = Figure.Length();
NCollection_Array2<occ::handle<MAT2d_Connexion>> Connexion(1, NbLines, 1, NbLines);
indStart = IndStart;
theDirection = 1.;
if (Sense)
{
theDirection = -1.;
}
//----------------------------------------------------------------------
// Calcul des connexions qui realisent le minimum de distance entre les
// differents elements de la figure.
//----------------------------------------------------------------------
for (i = 1; i < NbLines; i++)
{
for (j = i + 1; j <= NbLines; j++)
{
Connexion(i, j) = MinimumL1L2(Figure, i, j);
Connexion(j, i) = Connexion(i, j)->Reverse();
}
}
NCollection_Sequence<int> Set1;
NCollection_Sequence<int> Set2;
double DistS1S2;
int IndiceLine1, IndiceLine2;
int ISuiv = 0, MinOnSet1 = 0, MinOnSet2 = 0;
//---------------------------------------------------------------------------
// - 0 Set1 est initialise avec la ligne de depart.
// Set2 contient toutes les autres.
//---------------------------------------------------------------------------
Set1.Append(IndStart);
for (i = 1; i <= NbLines; i++)
{
if (i != IndStart)
{
Set2.Append(i);
}
}
//---------------------------------------------------------------------------
// - 1 Recherche de la connexion C la plus courte entre Set1 et Set2.
// - 2 La ligne de Set2 realisant le minimum de distance est inseree dans
// Set1 et supprime dans Set2.
// - 3 Insertion de la connexion dans l ensemble des connexions.
// - 4 Si Set2 est non vide retour en 1.
//---------------------------------------------------------------------------
while (!Set2.IsEmpty())
{
DistS1S2 = RealLast();
for (i = 1; i <= Set1.Length(); i++)
{
IndiceLine1 = Set1.Value(i);
for (j = 1; j <= Set2.Length(); j++)
{
IndiceLine2 = Set2.Value(j);
if (Connexion(IndiceLine1, IndiceLine2)->Distance() < DistS1S2)
{
ISuiv = j;
DistS1S2 = Connexion(IndiceLine1, IndiceLine2)->Distance();
MinOnSet1 = IndiceLine1;
MinOnSet2 = IndiceLine2;
}
}
}
Set1.Append(Set2.Value(ISuiv));
Set2.Remove(ISuiv);
Append(Connexion(MinOnSet1, MinOnSet2));
}
//----------------------------------------------------------------
// Construction du chemin en parcourant l ensemble des connexions.
//----------------------------------------------------------------
RunOnConnexions();
}
//============================================================================
// function : Append
// purpose : Insertion d une nouvelle connexion dans le chemin.
//
// Les connexions et les lignes constituent un arbre dont
// - les noeuds sont les lignes.
// - les connexions sont les branches.
//
//============================================================================
void MAT2d_MiniPath::Append(const occ::handle<MAT2d_Connexion>& C)
{
occ::handle<MAT2d_Connexion> CC;
if (!theConnexions.IsBound(C->IndexFirstLine()))
{
NCollection_Sequence<occ::handle<MAT2d_Connexion>> Seq;
theConnexions.Bind(C->IndexFirstLine(), Seq);
theConnexions(C->IndexFirstLine()).Append(C);
theFather.Bind(C->IndexSecondLine(), C);
return;
}
NCollection_Sequence<occ::handle<MAT2d_Connexion>>& Seq = theConnexions(C->IndexFirstLine());
int IndexAfter = 0;
int NbConnexions = Seq.Length();
for (int i = 1; i <= NbConnexions; i++)
{
CC = Seq.Value(i);
if (CC->IsAfter(C, theDirection))
{
IndexAfter = i;
break;
}
}
//----------------------------------------------------------------------
// Insertion de <C> avant <IAfter>.
// Si <IAfter> = 0 => Pas de connexions apres <C> => <C> est la
// derniere.
//----------------------------------------------------------------------
if (IndexAfter == 0)
{
Seq.Append(C);
}
else
{
Seq.InsertBefore(IndexAfter, C);
}
theFather.Bind(C->IndexSecondLine(), C);
}
//============================================================================
// function : Path
// purpose : Retour de la sequence de connexions definissant le chemin.
//============================================================================
const NCollection_Sequence<occ::handle<MAT2d_Connexion>>& MAT2d_MiniPath::Path() const
{
return thePath;
}
//=================================================================================================
bool MAT2d_MiniPath::IsConnexionsFrom(const int i) const
{
return (theConnexions.IsBound(i));
}
//============================================================================
// function : Connexions
// purpose : Retour de la sequence de connexions issue de la ligne <i>.
//============================================================================
NCollection_Sequence<occ::handle<MAT2d_Connexion>>& MAT2d_MiniPath::ConnexionsFrom(const int i)
{
return theConnexions.ChangeFind(i);
}
//=================================================================================================
bool MAT2d_MiniPath::IsRoot(const int ILine) const
{
return (ILine == indStart);
}
//============================================================================
// function : Father
// purpose : Retour de la premiere connexion qui arrive sur la ligne i
//============================================================================
occ::handle<MAT2d_Connexion> MAT2d_MiniPath::Father(const int ILine)
{
return theFather.ChangeFind(ILine);
}
//============================================================================
// function : RunOnConnexions
// purpose : Construction de <thePath> en parcourant <theConnexions>.
//============================================================================
void MAT2d_MiniPath::RunOnConnexions()
{
int i;
occ::handle<MAT2d_Connexion> C;
const NCollection_Sequence<occ::handle<MAT2d_Connexion>>& SC = theConnexions(indStart);
thePath.Clear();
for (i = 1; i <= SC.Length(); i++)
{
C = SC.Value(i);
thePath.Append(C);
ExploSons(thePath, C);
thePath.Append(C->Reverse());
}
}
//=================================================================================================
void MAT2d_MiniPath::ExploSons(NCollection_Sequence<occ::handle<MAT2d_Connexion>>& CResult,
const occ::handle<MAT2d_Connexion>& CRef)
{
int i;
int Index = CRef->IndexSecondLine();
if (!theConnexions.IsBound(Index))
{
return;
}
const NCollection_Sequence<occ::handle<MAT2d_Connexion>>& SC = theConnexions(Index);
occ::handle<MAT2d_Connexion> CRR = CRef->Reverse();
occ::handle<MAT2d_Connexion> C;
for (i = 1; i <= SC.Length(); i++)
{
C = SC.Value(i);
if (C->IsAfter(CRR, theDirection))
{
CResult.Append(C);
ExploSons(CResult, C);
CResult.Append(C->Reverse());
}
}
for (i = 1; i <= SC.Length(); i++)
{
C = SC.Value(i);
if (!C->IsAfter(CRR, theDirection))
{
CResult.Append(C);
ExploSons(CResult, C);
CResult.Append(C->Reverse());
}
else
{
break;
}
}
}
//============================================================================
// function : MinimumL1L2
// purpose : Calcul de la connexion realisant le minimum de distance entre les
// lignes d indice <IL1> et <IL2> dans <Figure>.
//============================================================================
occ::handle<MAT2d_Connexion> MAT2d_MiniPath::MinimumL1L2(
const NCollection_Sequence<NCollection_Sequence<occ::handle<Geom2d_Geometry>>>& Figure,
const int IL1,
const int IL2) const
{
Extrema_POnCurv2d PointOnCurv1, PointOnCurv2;
int IC1, IC2, IMinC1 = 0, IMinC2 = 0, i;
double DistL1L2_2, DistP1P2_2;
double ParameterOnC1 = 0., ParameterOnC2 = 0.;
NCollection_Sequence<occ::handle<Geom2d_Geometry>> L1, L2;
gp_Pnt2d Point1, Point2, P1, P2;
occ::handle<Geom2d_Curve> Item1;
occ::handle<Geom2d_Curve> Item2;
L1 = Figure.Value(IL1);
L2 = Figure.Value(IL2);
DistL1L2_2 = RealLast();
//---------------------------------------------------------------------------
// Calcul des extremas de distances entre les composants de L1 et de L2.
//---------------------------------------------------------------------------
for (IC1 = 1; IC1 <= L1.Length(); IC1++)
{
occ::handle<Standard_Type> Type1 = L1.Value(IC1)->DynamicType();
if (Type1 != STANDARD_TYPE(Geom2d_CartesianPoint))
{
Item1 = occ::down_cast<Geom2d_Curve>(L1.Value(IC1));
}
else
{
P1 = occ::down_cast<Geom2d_Point>(L1.Value(IC1))->Pnt2d();
}
for (IC2 = 1; IC2 <= L2.Length(); IC2++)
{
occ::handle<Standard_Type> Type2 = L2.Value(IC2)->DynamicType();
if (Type2 != STANDARD_TYPE(Geom2d_CartesianPoint))
{
Item2 = occ::down_cast<Geom2d_Curve>(L2.Value(IC2));
}
else
{
P2 = occ::down_cast<Geom2d_Point>(L2.Value(IC2))->Pnt2d();
}
if (Type1 == STANDARD_TYPE(Geom2d_CartesianPoint)
&& Type2 == STANDARD_TYPE(Geom2d_CartesianPoint))
{
DistP1P2_2 = P1.SquareDistance(P2);
if (DistP1P2_2 <= DistL1L2_2)
{
DistL1L2_2 = DistP1P2_2;
IMinC1 = IC1;
IMinC2 = IC2;
Point1 = P1;
Point2 = P2;
ParameterOnC1 = 0.;
ParameterOnC2 = 0.;
}
}
else if (Type1 == STANDARD_TYPE(Geom2d_CartesianPoint))
{
Geom2dAdaptor_Curve C2(Item2);
Extrema_ExtPC2d Extremas(P1, C2);
if (Extremas.IsDone())
{
for (i = 1; i <= Extremas.NbExt(); i++)
{
if (Extremas.SquareDistance(i) < DistL1L2_2)
{
DistL1L2_2 = Extremas.SquareDistance(i);
IMinC1 = IC1;
IMinC2 = IC2;
PointOnCurv2 = Extremas.Point(i);
ParameterOnC1 = 0.;
ParameterOnC2 = PointOnCurv2.Parameter();
Point1 = P1;
Point2 = PointOnCurv2.Value();
}
}
}
}
else if (Type2 == STANDARD_TYPE(Geom2d_CartesianPoint))
{
Geom2dAdaptor_Curve C1(Item1);
Extrema_ExtPC2d Extremas(P2, C1);
if (Extremas.IsDone())
{
for (i = 1; i <= Extremas.NbExt(); i++)
{
if (Extremas.SquareDistance(i) < DistL1L2_2)
{
DistL1L2_2 = Extremas.SquareDistance(i);
IMinC1 = IC1;
IMinC2 = IC2;
PointOnCurv1 = Extremas.Point(i);
ParameterOnC2 = 0.;
ParameterOnC1 = PointOnCurv1.Parameter();
Point1 = PointOnCurv1.Value();
Point2 = P2;
}
}
}
}
else
{
Geom2dAdaptor_Curve C1(Item1);
Geom2dAdaptor_Curve C2(Item2);
Extrema_ExtCC2d Extremas(C1, C2);
if (!Extremas.IsParallel() && Extremas.IsDone())
{
for (i = 1; i <= Extremas.NbExt(); i++)
{
if (Extremas.SquareDistance(i) < DistL1L2_2)
{
DistL1L2_2 = Extremas.SquareDistance(i);
IMinC1 = IC1;
IMinC2 = IC2;
Extremas.Points(i, PointOnCurv1, PointOnCurv2);
ParameterOnC1 = PointOnCurv1.Parameter();
ParameterOnC2 = PointOnCurv2.Parameter();
Point1 = PointOnCurv1.Value();
Point2 = PointOnCurv2.Value();
}
}
}
}
}
}
occ::handle<MAT2d_Connexion> ConnexionL1L2;
ConnexionL1L2 = new MAT2d_Connexion(IL1,
IL2,
IMinC1,
IMinC2,
sqrt(DistL1L2_2),
ParameterOnC1,
ParameterOnC2,
Point1,
Point2);
return ConnexionL1L2;
}