mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-06-25 12:04:07 +03:00
Main changes are in "IntWalk_IWalking::TestDeflection(...)" function (IntWalk_IWalking_5.gxx). Some test cases were corrected according to their new behavior.
510 lines
19 KiB
Plaintext
510 lines
19 KiB
Plaintext
// Copyright (c) 1995-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 <NCollection_IncAllocator.hxx>
|
|
#include <NCollection_LocalArray.hxx>
|
|
|
|
|
|
// modified by NIZHNY-MKK Thu Nov 2 15:07:26 2000.BEGIN
|
|
static Standard_Boolean TestPassedSolutionWithNegativeState(const IntWalk_VectorOfWalkingData& wd,
|
|
const TColStd_SequenceOfReal& Umult,
|
|
const TColStd_SequenceOfReal& Vmult,
|
|
const Standard_Real& prevUp,
|
|
const Standard_Real& prevVp,
|
|
const IntWalk_VectorOfInteger& nbMultiplicities,
|
|
const math_Vector& tolerance,
|
|
TheIWFunction& sp,
|
|
math_Vector& UV,
|
|
Standard_Integer& Irang);
|
|
// modified by NIZHNY-MKK Thu Nov 2 15:07:39 2000.END
|
|
|
|
|
|
void IntWalk_IWalking::ComputeOpenLine(const TColStd_SequenceOfReal& Umult,
|
|
const TColStd_SequenceOfReal& Vmult,
|
|
const ThePOPIterator& Pnts1,
|
|
TheIWFunction& Func,
|
|
Standard_Boolean& Rajout)
|
|
|
|
// Processing of open line.
|
|
//
|
|
// 1) for any starting point, which is not passing and not tangent and not yet processed,
|
|
// calculation of the step of advancement = step depending on the arrow and the maximum step.
|
|
//
|
|
// 2) calculate a point of approach (this point is on the tangent to the section
|
|
// of distance = no point in the interior)
|
|
//
|
|
// 3) conditions {
|
|
// (all calculated points do not exceed a point in the
|
|
// list of starting points)
|
|
// or
|
|
// (all points do not form an open line going
|
|
// from one border of the domain to the other or from a point tangent
|
|
// to border or from 2 tangent points : single cases)
|
|
//
|
|
// 1) framing of approached point on borders if necessary (there is
|
|
// calculation of step)
|
|
// 2) calculation of the point
|
|
// 3) if the point is not found the step is divided
|
|
// 4) stpo tests
|
|
// 5) calculation of the step depending on the arrow and the max step,
|
|
// (TestDeflection)
|
|
// stop possible.
|
|
// end of conditions.
|
|
|
|
{
|
|
Standard_Integer I, N;
|
|
Standard_Real aBornInf[2], aBornSup[2], aUVap[2];
|
|
math_Vector BornInf(aBornInf,1,2), BornSup(aBornSup,1,2), UVap(aUVap,1,2);
|
|
Standard_Real PasC, PasCu, PasCv;
|
|
Standard_Boolean Arrive; // shows if the line ends
|
|
Standard_Boolean Cadre; // shows if one is on border of the domain
|
|
Standard_Boolean ArretAjout; //shows if one is on added point
|
|
IntSurf_PntOn2S Psol;
|
|
Handle(IntWalk_TheIWLine) CurrentLine; // line under construction
|
|
Standard_Boolean Tgtend;
|
|
|
|
IntWalk_StatusDeflection Status, StatusPrecedent;
|
|
|
|
Standard_Integer NbDivision;
|
|
// number of divisions of step for each section
|
|
|
|
Standard_Integer StepSign;
|
|
|
|
ThePointOfPath PathPnt;
|
|
|
|
BornInf(1) = Um;
|
|
BornSup(1) = UM;
|
|
BornInf(2) = Vm;
|
|
BornSup(2) = VM;
|
|
|
|
math_FunctionSetRoot Rsnld(Func, tolerance);
|
|
Standard_Integer nbPath = Pnts1.Length();
|
|
|
|
// modified by NIZHNY-MKK Fri Oct 27 12:32:34 2000.BEGIN
|
|
NCollection_LocalArray<Standard_Integer> movementdirectioninfoarr (nbPath + 1);
|
|
Standard_Integer* movementdirectioninfo = movementdirectioninfoarr;
|
|
for (I = 0; I <= nbPath; I++) {
|
|
movementdirectioninfo[I] = 0;
|
|
}
|
|
// modified by NIZHNY-MKK Fri Oct 27 12:32:38 2000.END
|
|
|
|
for (I = 1; I <= nbPath; I++) {
|
|
//start point of the progression
|
|
// if (wd1[I].etat > 11) {
|
|
// modified by NIZHNY-MKK Fri Oct 27 12:33:37 2000.BEGIN
|
|
if ((wd1[I].etat > 11) || ((wd1[I].etat < -11) && (movementdirectioninfo[I]!=0))) {
|
|
// modified by NIZHNY-MKK Fri Oct 27 12:33:43 2000.END
|
|
PathPnt = Pnts1.Value(I);
|
|
CurrentLine = new IntWalk_TheIWLine (new NCollection_IncAllocator());
|
|
CurrentLine->SetTangencyAtBegining(Standard_False);
|
|
Tgtend = Standard_False;
|
|
CurrentLine->AddStatusFirst(Standard_False, Standard_True, I, PathPnt);
|
|
UVap(1) = wd1[I].ustart;
|
|
UVap(2) = wd1[I].vstart;
|
|
MakeWalkingPoint(11, UVap(1), UVap(2), Func, previousPoint);
|
|
previousd3d = Func.Direction3d();
|
|
previousd2d = Func.Direction2d();
|
|
CurrentLine->AddPoint(previousPoint);
|
|
// modified by NIZHNY-MKK Fri Oct 27 12:34:32 2000.BEGIN
|
|
if(movementdirectioninfo[I] !=0) {
|
|
if(movementdirectioninfo[I] < 0) {
|
|
StepSign = -1;
|
|
CurrentLine->SetTangentVector(previousd3d.Reversed(),1);
|
|
} else {
|
|
StepSign = 1;
|
|
CurrentLine->SetTangentVector(previousd3d,1);
|
|
}
|
|
} else {
|
|
Standard_Real tyutuyt=ThePointOfPathTool::Direction3d(PathPnt) * previousd3d;
|
|
if( tyutuyt < 0) {
|
|
StepSign = -1;
|
|
CurrentLine->SetTangentVector(previousd3d.Reversed(),1);
|
|
}
|
|
else {
|
|
StepSign = 1;
|
|
CurrentLine->SetTangentVector(previousd3d,1);
|
|
}
|
|
}
|
|
// modified by NIZHNY-MKK Fri Oct 27 12:34:37 2000.END
|
|
|
|
// Modified by Sergey KHROMOV - Tue Nov 20 10:41:45 2001 Begin
|
|
wd1[I].etat = - abs(wd1[I].etat);
|
|
movementdirectioninfo[I] = (movementdirectioninfo[I]==0) ? StepSign : 0;
|
|
// Modified by Sergey KHROMOV - Tue Nov 20 10:41:56 2001 End
|
|
// first step of advancement
|
|
Standard_Real d2dx = Abs(previousd2d.X());
|
|
Standard_Real d2dy = Abs(previousd2d.Y());
|
|
if (d2dx < tolerance(1)) {
|
|
PasC = pas * (VM-Vm)/d2dy;
|
|
}
|
|
else if (d2dy < tolerance(2)) {
|
|
PasC = pas * (UM-Um)/d2dx;
|
|
}
|
|
else {
|
|
PasC = pas * Min((UM-Um)/d2dx,(VM-Vm)/d2dy);
|
|
}
|
|
|
|
Arrive = Standard_False;
|
|
ArretAjout = Standard_False;
|
|
NbDivision = 0;
|
|
StatusPrecedent = IntWalk_OK;
|
|
// modified by NIZHNY-MKK Fri Oct 27 12:39:37 2000
|
|
Standard_Integer IndexOfPathPointDoNotCheck=0;
|
|
Standard_Integer aNbIter = 10;
|
|
while (!Arrive) { // as one of stop tests is not checked
|
|
Cadre = Cadrage(BornInf,BornSup,UVap,PasC,StepSign);
|
|
// Border?
|
|
|
|
#ifdef CHRONO
|
|
Chronrsnld.Start();
|
|
#endif
|
|
|
|
Rsnld.Perform(Func,UVap,BornInf,BornSup);
|
|
|
|
#ifdef CHRONO
|
|
Chronrsnld.Stop();
|
|
#endif
|
|
|
|
if (Cadre) {
|
|
BornInf(1) = Um; BornSup(1) = UM; BornInf(2) = Vm; BornSup(2) = VM;
|
|
}
|
|
if (Rsnld.IsDone()) {
|
|
if (Abs(Func.Root()) > Func.Tolerance()) {
|
|
PasC = PasC / 2.0;
|
|
PasCu = Abs(PasC*previousd2d.X());
|
|
PasCv = Abs(PasC*previousd2d.Y());
|
|
if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
|
|
if (CurrentLine->NbPoints() == 1) break;
|
|
Arrive = Standard_True;
|
|
CurrentLine->AddStatusLast(Standard_False);
|
|
Tgtend = Standard_True; // check
|
|
Rajout = Standard_True;
|
|
seqAjout.Append(lines.Length() + 1);
|
|
}
|
|
}
|
|
else { // test stop
|
|
Rsnld.Root(UVap);
|
|
Arrive = TestArretPassage(Umult, Vmult, Func, UVap, N);
|
|
if (Arrive) {
|
|
Cadre = Standard_False;
|
|
//in case if there is a frame and arrive at the same time
|
|
}
|
|
else {
|
|
if (Rajout) {
|
|
ArretAjout =TestArretAjout(Func, UVap, N, Psol);
|
|
if (ArretAjout) {
|
|
// jag 940615
|
|
Tgtend = lines.Value(N)->IsTangentAtEnd();
|
|
N = -N;
|
|
}
|
|
}
|
|
// modified by NIZHNY-MKK Thu Nov 2 15:09:08 2000.BEGIN
|
|
if(!(Rajout && ArretAjout)) {
|
|
Standard_Real prevUp, prevVp;
|
|
if (!reversed) {
|
|
previousPoint.ParametersOnS2(prevUp, prevVp);
|
|
}
|
|
else {
|
|
previousPoint.ParametersOnS1(prevUp, prevVp);
|
|
}
|
|
Arrive = TestPassedSolutionWithNegativeState(wd1, Umult, Vmult, prevUp, prevVp,
|
|
nbMultiplicities, tolerance, Func, UVap, N);
|
|
if(Arrive) {
|
|
Cadre = Standard_False;
|
|
}
|
|
}
|
|
// modified by NIZHNY-MKK Thu Nov 2 15:09:13 2000.END
|
|
if (!ArretAjout && Cadre) {
|
|
if (CurrentLine->NbPoints() == 1) break; // cancel the line
|
|
TestArretCadre(Umult, Vmult, CurrentLine, Func, UVap, N);
|
|
// if (N == 0) {
|
|
if (N <= 0) { // jag 941017
|
|
MakeWalkingPoint(2, UVap(1), UVap(2), Func, Psol);
|
|
Tgtend = Func.IsTangent();
|
|
N = -N;
|
|
}
|
|
}
|
|
}
|
|
Status = TestDeflection(Func, Arrive, UVap, StatusPrecedent,
|
|
NbDivision,PasC,StepSign);
|
|
StatusPrecedent = Status;
|
|
if (Status == IntWalk_PasTropGrand) {
|
|
Arrive = Standard_False;
|
|
ArretAjout = Standard_False;
|
|
Tgtend = Standard_False; // jag 940615
|
|
if (!reversed) {
|
|
previousPoint.ParametersOnS2(UVap(1), UVap(2));
|
|
}
|
|
else {
|
|
previousPoint.ParametersOnS1(UVap(1), UVap(2));
|
|
}
|
|
}
|
|
else if (ArretAjout || Cadre) {
|
|
Arrive = Standard_True;
|
|
CurrentLine->AddStatusLast(Standard_False);
|
|
if (Status != IntWalk_ArretSurPointPrecedent) {
|
|
CurrentLine->AddPoint(Psol);
|
|
}
|
|
if (Cadre && N==0) {
|
|
Rajout = Standard_True;
|
|
seqAjout.Append(lines.Length()+1);
|
|
}
|
|
}
|
|
else if (Status == IntWalk_ArretSurPointPrecedent) {
|
|
if (CurrentLine->NbPoints() == 1) { //cancel the line
|
|
Arrive = Standard_False;
|
|
break;
|
|
}
|
|
Arrive = Standard_True;
|
|
Rajout = Standard_True;
|
|
seqAjout.Append(lines.Length() + 1);
|
|
CurrentLine->AddStatusLast(Standard_False);
|
|
Tgtend = Standard_True; // check
|
|
}
|
|
else if (Arrive) {
|
|
if (CurrentLine->NbPoints() == 1 && // cancel the line
|
|
(N == I || Status == IntWalk_PointConfondu) ) {
|
|
// if N == I the main uv is probably lost
|
|
// or the point is a point of accumulation
|
|
// if point is confused the start data is bad
|
|
Arrive = Standard_False;
|
|
break;
|
|
}
|
|
// necessairily N > 0 jag 940617
|
|
// point of stop given at input
|
|
PathPnt = Pnts1.Value(N);
|
|
|
|
Standard_Integer etat1N=wd1[N].etat;
|
|
// modified by NIZHNY-MKK Thu Nov 2 15:09:51 2000.BEGIN
|
|
// if (etat1N < 11) { // passing point that is a stop
|
|
if (Abs(etat1N) < 11) { // passing point that is a stop
|
|
// modified by NIZHNY-MKK Thu Nov 2 15:12:11 2000.END
|
|
if (Status == IntWalk_ArretSurPoint) {
|
|
CurrentLine->AddStatusLast(Standard_False);
|
|
Tgtend = Standard_True; // need check
|
|
}
|
|
else {
|
|
Arrive = Standard_False;
|
|
}
|
|
CurrentLine->AddIndexPassing(N);
|
|
}
|
|
else { // point of stop given at input
|
|
if (etat1N == 11) {
|
|
Tgtend = Standard_True;
|
|
}
|
|
CurrentLine->AddStatusLast(Standard_True, N, PathPnt);
|
|
}
|
|
AddPointInCurrentLine(N,PathPnt,CurrentLine);
|
|
if ((etat1N != 1 && etat1N != 11)) {
|
|
// modified by NIZHNY-MKK Fri Oct 27 12:43:05 2000.BEGIN
|
|
// wd1[N].etat= - wd1[N].etat;
|
|
wd1[N].etat = - Abs(etat1N);
|
|
movementdirectioninfo[N] = (movementdirectioninfo[N]==0) ? StepSign : 0;
|
|
if(Arrive && movementdirectioninfo[N]!=0) {
|
|
IndexOfPathPointDoNotCheck = N;
|
|
}
|
|
|
|
if(Arrive) {
|
|
Rajout = Standard_True;
|
|
seqAjout.Append(lines.Length() + 1);
|
|
}
|
|
// modified by NIZHNY-MKK Fri Oct 27 12:45:33 2000.END
|
|
}
|
|
}
|
|
else if (Status == IntWalk_ArretSurPoint) {
|
|
Arrive = Standard_True;
|
|
CurrentLine->AddStatusLast(Standard_False);
|
|
Tgtend = Standard_True;
|
|
MakeWalkingPoint(1, UVap(1), UVap(2), Func, Psol);
|
|
CurrentLine->AddPoint(Psol);
|
|
Rajout = Standard_True;
|
|
seqAjout.Append(lines.Length() + 1);
|
|
}
|
|
else if (Status == IntWalk_OK) {
|
|
MakeWalkingPoint(2, UVap(1), UVap(2), Func, previousPoint);
|
|
previousd3d = Func.Direction3d();
|
|
previousd2d = Func.Direction2d();
|
|
CurrentLine->AddPoint(previousPoint);
|
|
}
|
|
else if (Status == IntWalk_PointConfondu)
|
|
{
|
|
aNbIter --;
|
|
}
|
|
}
|
|
}
|
|
else { // no numerical solution
|
|
PasC = PasC / 2.;
|
|
PasCu = Abs(PasC*previousd2d.X());
|
|
PasCv = Abs(PasC*previousd2d.Y());
|
|
if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
|
|
if (CurrentLine->NbPoints()==1) break;
|
|
Arrive = Standard_True;
|
|
CurrentLine->AddStatusLast(Standard_False);
|
|
Tgtend = Standard_True; // need check
|
|
Rajout = Standard_True;
|
|
seqAjout.Append(lines.Length() + 1);
|
|
}
|
|
}
|
|
|
|
if(aNbIter < 0)
|
|
break;
|
|
} // end of started line
|
|
|
|
if (Arrive) {
|
|
CurrentLine->SetTangencyAtEnd(Tgtend);
|
|
lines.Append(CurrentLine);
|
|
// modified by NIZHNY-MKK Fri Oct 27 12:59:29 2000.BEGIN
|
|
movementdirectioninfo[I]=0;
|
|
if(wd1[I].etat > 0)
|
|
// modified by NIZHNY-MKK Fri Oct 27 12:59:42 2000.END
|
|
wd1[I].etat=-wd1[I].etat;
|
|
|
|
//-- lbr le 5 juin 97 (Pb ds Contap)
|
|
for(Standard_Integer av=1; av<=nbPath; av++) {
|
|
// modified by NIZHNY-MKK Fri Oct 27 13:00:22 2000.BEGIN
|
|
// if (wd1[av].etat > 11) {
|
|
if ((wd1[av].etat > 11) ||
|
|
((av!=I) &&
|
|
(av!=IndexOfPathPointDoNotCheck) &&
|
|
(wd1[av].etat < -11) &&
|
|
(movementdirectioninfo[av]!=0)))
|
|
{
|
|
// modified by NIZHNY-MKK Fri Oct 27 13:00:26 2000.END
|
|
Standard_Real Uav=wd1[av].ustart;
|
|
Standard_Real Vav=wd1[av].vstart;
|
|
Standard_Real Uavp,Vavp;
|
|
const IntSurf_PntOn2S &avP=CurrentLine->Value(CurrentLine->NbPoints());
|
|
if (!reversed) {
|
|
avP.ParametersOnS2(Uavp,Vavp);
|
|
}
|
|
else {
|
|
avP.ParametersOnS1(Uavp,Vavp);
|
|
}
|
|
Uav-=Uavp;
|
|
Vav-=Vavp;
|
|
Uav*=0.001; Vav*=0.001;
|
|
if(Abs(Uav)<tolerance(1) && Abs(Vav)<tolerance(2)) {
|
|
// modified by NIZHNY-MKK Fri Oct 27 13:01:38 2000.BEGIN
|
|
// wd1[av].etat=-wd1[av].etat;
|
|
if(wd1[av].etat < 0) {
|
|
movementdirectioninfo[av] = 0;
|
|
} else {
|
|
wd1[av].etat=-wd1[av].etat;
|
|
movementdirectioninfo[av] = StepSign;
|
|
}
|
|
// modified by NIZHNY-MKK Fri Oct 27 13:01:42 2000.END
|
|
CurrentLine->AddStatusLast(Standard_True, av, Pnts1.Value(av));
|
|
//-- cout<<"\n Debug ? lbr ds IntWalk_IWalking_3.gxx"<<endl;
|
|
}
|
|
|
|
const IntSurf_PntOn2S &avPP=CurrentLine->Value(1);
|
|
if (!reversed) {
|
|
avPP.ParametersOnS2(Uavp,Vavp);
|
|
}
|
|
else {
|
|
avPP.ParametersOnS1(Uavp,Vavp);
|
|
}
|
|
Uav=wd1[av].ustart;
|
|
Vav=wd1[av].vstart;
|
|
Uav-=Uavp;
|
|
Vav-=Vavp;
|
|
Uav*=0.001; Vav*=0.001;
|
|
if(Abs(Uav)<tolerance(1) && Abs(Vav)<tolerance(2)) {
|
|
// modified by NIZHNY-MKK Fri Oct 27 13:02:49 2000.BEGIN
|
|
// wd1[av].etat=-wd1[av].etat;
|
|
if(wd1[av].etat < 0) {
|
|
movementdirectioninfo[av] = 0;
|
|
} else {
|
|
wd1[av].etat=-wd1[av].etat;
|
|
movementdirectioninfo[av] = -StepSign;
|
|
}
|
|
// modified by NIZHNY-MKK Fri Oct 27 13:02:52 2000.END
|
|
//-- cout<<"\n Debug ? lbr ds IntWalk_IWalking_3.gxx"<<endl;
|
|
CurrentLine->AddStatusFirst(Standard_False, Standard_True, av, Pnts1.Value(av));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} //end of point processing
|
|
} //end of all points
|
|
}
|
|
|
|
// modified by NIZHNY-MKK Thu Nov 2 15:07:53 2000.BEGIN
|
|
static Standard_Boolean TestPassedSolutionWithNegativeState(const IntWalk_VectorOfWalkingData& wd,
|
|
const TColStd_SequenceOfReal& Umult,
|
|
const TColStd_SequenceOfReal& Vmult,
|
|
const Standard_Real& prevUp,
|
|
const Standard_Real& prevVp,
|
|
const IntWalk_VectorOfInteger& nbMultiplicities,
|
|
const math_Vector& tolerance,
|
|
TheIWFunction& sp,
|
|
math_Vector& UV,
|
|
Standard_Integer& Irang) {
|
|
Standard_Boolean Arrive = Standard_False;
|
|
Standard_Real Dup, Dvp, Utest,Vtest;
|
|
Standard_Real tolu = tolerance(1);
|
|
Standard_Real tolv = tolerance(2);
|
|
Standard_Integer i, j, k, N;
|
|
for (i = 1; i < (int)wd.size(); i++) {
|
|
if (wd[i].etat < -11) {
|
|
|
|
// debug jag see with isg
|
|
|
|
Utest = wd[i].ustart;
|
|
Vtest = wd[i].vstart;
|
|
Dup = prevUp - Utest;
|
|
Dvp = prevVp - Vtest;
|
|
if (Abs(Dup) >= tolu || Abs(Dvp) >= tolv) {
|
|
Standard_Real UV1mUtest = UV(1)-Utest;
|
|
Standard_Real UV2mVtest = UV(2)-Vtest;
|
|
if(( (Dup*UV1mUtest + Dvp*UV2mVtest) < 0) ||
|
|
( Abs(UV1mUtest) < tolu
|
|
&& Abs(UV2mVtest) < tolv)) {
|
|
Irang=i;
|
|
Arrive = Standard_True;
|
|
UV(1) = Utest;
|
|
UV(2) = Vtest;
|
|
}
|
|
else if (nbMultiplicities[i] > 0) {
|
|
N=0;
|
|
for (k = 1; k < i; k++) {
|
|
N+=nbMultiplicities[k];
|
|
}
|
|
for (j = N + 1; j <= N + nbMultiplicities[i]; j++) {
|
|
if (((prevUp-Umult(j))*(UV(1)-Umult(j)) +
|
|
(prevVp-Vmult(j))*(UV(2)-Vmult(j)) < 0) ||
|
|
(Abs(UV(1)-Umult(j)) < tolu &&
|
|
Abs(UV(2)-Vmult(j)) < tolv)) {
|
|
Irang=i;
|
|
Arrive = Standard_True;
|
|
UV(1) = Utest;
|
|
UV(2) = Vtest;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (Arrive) {
|
|
Standard_Real abidF[1], abidD[1][2];
|
|
math_Vector bidF(abidF,1,1);
|
|
math_Matrix bidD(abidD,1,1,1,2);
|
|
sp.Values(UV,bidF,bidD);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return Arrive;
|
|
}
|
|
// modified by NIZHNY-MKK Thu Nov 2 15:07:58 2000.END
|