From: Pablo Garzon <garzon@ei-pfe-706.creatis.insa-lyon.fr>
Date: Mon, 27 Mar 2023 14:14:01 +0000 (+0200)
Subject: #3501 Implementation Patch 3 points
X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=36a18a8a8665918949fe03050ea76f76dbc25560;p=creaMaracasVisu.git

#3501 Implementation Patch 3 points
---

diff --git a/bbtk/src/bbcreaMaracasVisuShowNPoints_Tools.cxx b/bbtk/src/bbcreaMaracasVisuShowNPoints_Tools.cxx
index f6068c1..99f5120 100644
--- a/bbtk/src/bbcreaMaracasVisuShowNPoints_Tools.cxx
+++ b/bbtk/src/bbcreaMaracasVisuShowNPoints_Tools.cxx
@@ -30,208 +30,278 @@ void ShowNPoints_Tools::NearestPointToMesh( vtkPoints *points,vtkStaticPointLoca
 
 void ShowNPoints_Tools::CreatePatch_3points()
 {
-    printf("EED ShowNPoints_Tools::CreatePatch_3points    Not Implemented !!!!");
-    printf("EED ShowNPoints_Tools::CreatePatch_3points    Not Implemented !!!!");
-    printf("EED ShowNPoints_Tools::CreatePatch_3points    Not Implemented !!!!");
-    printf("EED ShowNPoints_Tools::CreatePatch_3points    Not Implemented !!!!");
-    printf("EED ShowNPoints_Tools::CreatePatch_3points    Not Implemented !!!!");
-    printf("EED ShowNPoints_Tools::CreatePatch_3points    Not Implemented !!!!");
+	printf("PG ShowNPoints_Tools::CreatePatch_3points  Entered patch 3 points !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+	WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
+	wsp->StopAutoAddPoints();
+    wsp->StopTrackPoint();
+	if ( (wsp->GetLstModelShowNPointsSize()==1) &&
+         (wsp->GetModelShowNPoints()->GetLstPointsSize()==3) &&
+         (bbGetInputMesh()!=NULL ) )
+    {
+		std::vector<int> lstX = wsp->GetModelShowNPoints()->GetLstPointsX();
+		std::vector<int> lstY = wsp->GetModelShowNPoints()->GetLstPointsY();
+		std::vector<int> lstZ = wsp->GetModelShowNPoints()->GetLstPointsZ();
+		
+		double pA[3] = {lstX[0],lstY[0],lstZ[0]};
+		double pB[3] = {lstX[1],lstY[1],lstZ[1]};
+		double pC[3] = {lstX[2],lstY[2],lstZ[2]};
+		
+		double v[3];
+		double u[3];
+		vtkMath::Subtract(pC,pA,v);
+		vtkMath::Subtract(pB,pA,u);
+		
+		/**point in AC closest to B.
+		*formula t=(V)dot(U)/(V)dot(V)
+		*/
+		double t = vtkMath::Dot(v,u)/vtkMath::Dot(v,v);
+		/**nP found point
+		*formula A+t(C-A) -> A+tV
+		*/
+		vtkMath::MultiplyScalar(v, t);
+		double nP[3];
+		vtkMath::Add(pA, v, nP);
+		
+		//calculate direction vector from found point to B
+		double dirVector[3];
+		vtkMath::Subtract(pB, nP, dirVector);
+		
+		double pointAdd[3];
+		double pointSub[3];
+		
+		//Add and subtract direction vector to A and C to find the 4 points to create the patch,
+		
+		std::vector<int> resListX;
+		std::vector<int> resListY;
+		std::vector<int> resListZ;
+		
+		vtkMath::Add(pA, dirVector, pointAdd);
+		vtkMath::Subtract(pA, dirVector, pointSub);
+		
+		resListX.push_back(pointSub[0]);
+		resListY.push_back(pointSub[1]);
+		resListZ.push_back(pointSub[2]);
+
+		resListX.push_back(pointAdd[0]);
+		resListY.push_back(pointAdd[1]);
+		resListZ.push_back(pointAdd[2]);
+		
+		
+		vtkMath::Add(pC, dirVector, pointAdd);
+		vtkMath::Subtract(pC, dirVector, pointSub);
+		
+		resListX.push_back(pointAdd[0]);
+		resListY.push_back(pointAdd[1]);
+		resListZ.push_back(pointAdd[2]);
+		
+		resListX.push_back(pointSub[0]);
+		resListY.push_back(pointSub[1]);
+		resListZ.push_back(pointSub[2]);
+		printf("PG ShowNPoints_Tools::CreatePatch_3points  Calls CreatePatch_Points !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+		//Create patch given the previously calculated points (4 points)
+		CreatePatch_Points(resListX, resListY, resListZ);
+	}else{
+		printf("PG ShowNPoints_Tools::CreatePatch_3points  Warning patch not apply. Need only one group of 3 points\n");
+	}
 }
 
 void ShowNPoints_Tools::CreatePatch_4points()
 {
-    WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
-    wsp->StopAutoAddPoints();
+	WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
+	wsp->StopAutoAddPoints();
     wsp->StopTrackPoint();
-    if ( (wsp->GetLstModelShowNPointsSize()==1) &&
+	if ( (wsp->GetLstModelShowNPointsSize()==1) &&
          (wsp->GetModelShowNPoints()->GetLstPointsSize()==4) &&
          (bbGetInputMesh()!=NULL ) )
-    {
-        std::vector<long int>   lstIdNormalSurface;
-        double                  spc[3];
-                                spc[0]          = bbGetInputSpacing()[0];
-                                spc[1]          = bbGetInputSpacing()[1];
-                                spc[2]          = bbGetInputSpacing()[2];
-        vtkPoints               *points         = bbGetInputMesh()->GetPoints();
-        vtkStaticPointLocator   *pointLocator   = vtkStaticPointLocator::New();
-        pointLocator->SetDataSet( bbGetInputMesh() );
-        pointLocator->BuildLocator();
-        wsp->StopTrackPoint();
-        double p[3],pM[3];
-        double dx,dy,dz,s;
-        std::vector<int> lstX = wsp->GetModelShowNPoints()->GetLstPointsX();
-        std::vector<int> lstY = wsp->GetModelShowNPoints()->GetLstPointsY();
-        std::vector<int> lstZ = wsp->GetModelShowNPoints()->GetLstPointsZ();
-        wsp->ErasePoint( 0 );
-        wsp->ErasePoint( 0 );
-        wsp->ErasePoint( 0 );
-        wsp->ErasePoint( 0 );
-        // --- Group 0 ---
-        dx = lstX[1]-lstX[0];
-        dy = lstY[1]-lstY[0];
-        dz = lstZ[1]-lstZ[0];
-        s = 0;
-        p[0] = lstX[0] + dx*s;
-        p[1] = lstY[0] + dy*s;
-        p[2] = lstZ[0] + dz*s;
-        NearestPointToMesh(points, pointLocator, spc, p,pM);
-        wsp->InsertPoint(pM[0] ,pM[1], pM[2],"");
-        lstIdNormalSurface.push_back( pointLocator->FindClosestPoint(pM) );
-        s = 0.33333;
-        p[0] = lstX[0] + dx*s;
-        p[1] = lstY[0] + dy*s;
-        p[2] = lstZ[0] + dz*s;
-        NearestPointToMesh(points, pointLocator, spc, p,pM);
-        wsp->InsertPoint(pM[0] ,pM[1], pM[2],"");
-        s = 0.6666666;
-        p[0] = lstX[0] + dx*s;
-        p[1] = lstY[0] + dy*s;
-        p[2] = lstZ[0] + dz*s;
-        NearestPointToMesh(points, pointLocator, spc, p,pM);
-        wsp->InsertPoint(pM[0],pM[1], pM[2],"");
-        s = 1;
-        p[0] = lstX[0] + dx*s;
-        p[1] = lstY[0] + dy*s;
-        p[2] = lstZ[0] + dz*s;
-        NearestPointToMesh(points, pointLocator, spc, p,pM);
-        wsp->InsertPoint(pM[0],pM[1], pM[2],"");
-        lstIdNormalSurface.push_back( pointLocator->FindClosestPoint(pM) );
+    {    	     
+		std::vector<int> lstX = wsp->GetModelShowNPoints()->GetLstPointsX();
+		std::vector<int> lstY = wsp->GetModelShowNPoints()->GetLstPointsY();
+		std::vector<int> lstZ = wsp->GetModelShowNPoints()->GetLstPointsZ();
+		CreatePatch_Points(lstX, lstY, lstZ);
+    }else{
+		printf("PG ShowNPoints_Tools::CreatePatch_4points  Warning patch not apply. Need only one group of 4 points\n");
+	}
+}
 
-        // --- Group 1 ---
-        wsp->InsertCollectionAfter_();
-          p[0] = (lstX[0]+lstX[3])/2;
-          p[1] = (lstY[0]+lstY[3])/2;
-          p[2] = (lstZ[0]+lstZ[3])/2;
-          NearestPointToMesh(points, pointLocator, spc, p,pM);
-          wsp->InsertPoint(pM[0] ,pM[1], pM[2],"");
-          p[0] = (lstX[1]+lstX[2])/2;
-          p[1] = (lstY[1]+lstY[2])/2;
-          p[2] = (lstZ[1]+lstZ[2])/2;
-          NearestPointToMesh(points, pointLocator, spc, p,pM);
-          wsp->InsertPoint(pM[0] ,pM[1], pM[2],"");
-          p[0] = (lstX[0]+lstX[1]+lstX[2]+lstX[3])/4;          p[1] = (lstY[0]+lstY[1]+lstY[2]+lstY[3])/4;          p[2] = (lstZ[0]+lstZ[1]+lstZ[2]+lstZ[3])/4;
-          wsp->InsertPoint(p[0] ,p[1], p[2],"");
+void ShowNPoints_Tools::CreatePatch_Points(std::vector<int> lstX, std::vector<int> lstY, std::vector<int> lstZ)
+{
+    WidgetShowNPoints* wsp = bbGetInputWidgetShowNPoints();
+    std::vector<long int>   lstIdNormalSurface;
+    double                  spc[3];
+                            spc[0]          = bbGetInputSpacing()[0];
+                            spc[1]          = bbGetInputSpacing()[1];
+                            spc[2]          = bbGetInputSpacing()[2];
+    vtkPoints               *points         = bbGetInputMesh()->GetPoints();
+    vtkStaticPointLocator   *pointLocator   = vtkStaticPointLocator::New();
+    pointLocator->SetDataSet( bbGetInputMesh() );
+    pointLocator->BuildLocator();
+    wsp->StopTrackPoint();
+    double p[3],pM[3];
+    double dx,dy,dz;
+    
+    wsp->DeleteAllPoints_();
+    //wsp->ErasePoint( 0 );
+    //wsp->ErasePoint( 0 );
+    //wsp->ErasePoint( 0 );
+    //wsp->ErasePoint( 0 );
+    // --- Group 0 ---
+    dx = lstX[1]-lstX[0];
+    dy = lstY[1]-lstY[0];
+    dz = lstZ[1]-lstZ[0];
+    //
+    //
+    double part = 0.25;
+    for(int sect = 0; sect < 5; sect++)
+    {
+    	p[0] = lstX[0] + dx*(sect*part);
+		p[1] = lstY[0] + dy*(sect*part);
+		p[2] = lstZ[0] + dz*(sect*part);
+		if(sect == 4){
+			p[0] = p[0] + 0.5*(((lstX[1]+lstX[2])/2)-p[0]);
+			p[1] = p[1] + 0.5*(((lstY[1]+lstY[2])/2)-p[1]);
+			p[2] = p[2] + 0.5*(((lstZ[1]+lstZ[2])/2)-p[2]);
+		}
+		if(sect == 0){
+			p[0] = p[0] + 0.5*(((lstX[0]+lstX[3])/2)-p[0]);
+			p[1] = p[1] + 0.5*(((lstY[0]+lstY[3])/2)-p[1]);
+			p[2] = p[2] + 0.5*(((lstZ[0]+lstZ[3])/2)-p[2]);
+		}
+		NearestPointToMesh(points, pointLocator, spc, p,pM);
+		wsp->InsertPoint(pM[0] ,pM[1], pM[2],"");
+		
+		if(sect == 0 || sect == 4) lstIdNormalSurface.push_back( pointLocator->FindClosestPoint(pM) );
+    }
+	
+    // --- Group 1 ---
+    wsp->InsertCollectionAfter_();
+      p[0] = (lstX[0]+lstX[3])/2;
+      p[1] = (lstY[0]+lstY[3])/2;
+      p[2] = (lstZ[0]+lstZ[3])/2;
+      NearestPointToMesh(points, pointLocator, spc, p,pM);
+      wsp->InsertPoint(pM[0] ,pM[1], pM[2],"");
+      p[0] = (lstX[1]+lstX[2])/2;
+      p[1] = (lstY[1]+lstY[2])/2;
+      p[2] = (lstZ[1]+lstZ[2])/2;
+      NearestPointToMesh(points, pointLocator, spc, p,pM);
+      wsp->InsertPoint(pM[0] ,pM[1], pM[2],"");
+      p[0] = (lstX[0]+lstX[1]+lstX[2]+lstX[3])/4;          p[1] = (lstY[0]+lstY[1]+lstY[2]+lstY[3])/4;          p[2] = (lstZ[0]+lstZ[1]+lstZ[2]+lstZ[3])/4;
+      wsp->InsertPoint(p[0] ,p[1], p[2],"");
+	
+    // --- Group 2 ---
+    
+    wsp->InsertCollectionAfter_();
 
-        // --- Group 2 ---
-        wsp->InsertCollectionAfter_();
-          p[0] = lstX[3];
-          p[1] = lstY[3];
-          p[2] = lstZ[3];
-          NearestPointToMesh(points, pointLocator, spc, p,pM);
-          wsp->InsertPoint(pM[0] ,pM[1], pM[2],"");
-          lstIdNormalSurface.push_back( pointLocator->FindClosestPoint(p) );
-          p[0] = lstX[2];
-          p[1] = lstY[2];
-          p[2] = lstZ[2];
-          NearestPointToMesh(points, pointLocator, spc, p,pM);
-          wsp->InsertPoint(pM[0] ,pM[1], pM[2],"");
-          lstIdNormalSurface.push_back( pointLocator->FindClosestPoint(p) );
-          dx = lstX[2]-lstX[3];
-          dy = lstY[2]-lstY[3];
-          dz = lstZ[2]-lstZ[3];
-          s=0.33333;
-          p[0] = lstX[3] + dx*s;
-          p[1] = lstY[3] + dy*s;
-          p[2] = lstZ[3] + dz*s;
-          NearestPointToMesh(points, pointLocator, spc, p,pM);
-          wsp->InsertPoint(pM[0] ,pM[1], pM[2],"");
-          s=s*2;
-          p[0] = lstX[3] + dx*s;
-          p[1] = lstY[3] + dy*s;
-          p[2] = lstZ[3] + dz*s;
-          NearestPointToMesh(points, pointLocator, spc, p,pM);
-          wsp->InsertPoint(pM[0] ,pM[1], pM[2],"");
+    dx = lstX[2]-lstX[3];
+    dy = lstY[2]-lstY[3];
+    dz = lstZ[2]-lstZ[3];  
+    for(int sect = 0; sect < 5; sect++)
+    {
+    	p[0] = lstX[3] + dx*(sect*part);
+		p[1] = lstY[3] + dy*(sect*part);
+		p[2] = lstZ[3] + dz*(sect*part);
+		if(sect == 4){
+			p[0] = p[0] + 0.5*(((lstX[1]+lstX[2])/2)-p[0]);
+			p[1] = p[1] + 0.5*(((lstY[1]+lstY[2])/2)-p[1]);
+			p[2] = p[2] + 0.5*(((lstZ[1]+lstZ[2])/2)-p[2]);
+		}
+		if(sect == 0){
+			p[0] = p[0] + 0.5*(((lstX[0]+lstX[3])/2)-p[0]);
+			p[1] = p[1] + 0.5*(((lstY[0]+lstY[3])/2)-p[1]);
+			p[2] = p[2] + 0.5*(((lstZ[0]+lstZ[3])/2)-p[2]);
+		}
+		NearestPointToMesh(points, pointLocator, spc, p,pM);
+		wsp->InsertPoint(pM[0] ,pM[1], pM[2],"");
+		
+		if(sect == 0 || sect == 4) lstIdNormalSurface.push_back( pointLocator->FindClosestPoint(pM) );
+    }
 
-         pointLocator->Delete();
-        
-        // Check normals
+     pointLocator->Delete();
+    
+    // Check normals
 //        1. Recorrer las normales de lstIdNormals y calcular el promedio  -> V1
-        double          *nValue;
-		double 			n1[3];
-        vtkPointData    *pointdata  =  bbGetInputMesh()->GetPointData();
-        vtkDataArray    *dataarray  = pointdata->GetNormals();
-		int i,size = lstIdNormalSurface.size();
-		n1[0]=0;
-		n1[1]=0;
-		n1[2]=0;
-		for (i=0; i<size; i++)
-		{
-		    nValue        = dataarray->GetTuple3( lstIdNormalSurface[i] );
-			n1[0] = n1[0] + nValue[0];
-			n1[1] = n1[1] + nValue[1];
-			n1[2] = n1[2] + nValue[2];
-		} // for i
-		n1[0] = n1[0]/size;
-		n1[1] = n1[1]/size;
-		n1[2] = n1[2]/size;
+    double          *nValue;
+	double 			n1[3];
+    vtkPointData    *pointdata  =  bbGetInputMesh()->GetPointData();
+    vtkDataArray    *dataarray  = pointdata->GetNormals();
+	int i,size = lstIdNormalSurface.size();
+	n1[0]=0;
+	n1[1]=0;
+	n1[2]=0;
+	for (i=0; i<size; i++)
+	{
+	    nValue        = dataarray->GetTuple3( lstIdNormalSurface[i] );
+		n1[0] = n1[0] + nValue[0];
+		n1[1] = n1[1] + nValue[1];
+		n1[2] = n1[2] + nValue[2];
+	} // for i
+	n1[0] = n1[0]/size;
+	n1[1] = n1[1]/size;
+	n1[2] = n1[2]/size;
 
 //        2. Calcular el promedio de 4 normales de la nueva superficie     -> V2
-        double pC[3];
-        double pM1[3];
-        double pM2[3];
-        double n2[3];
-        n2[0] = 0;
-        n2[1] = 0;
-        n2[2] = 0;
-        // Collection 0 with 4 points
-        // Collection 1 with 3 points
-        // Collection 2 with 4 points
-        wsp->GetCollectionPoint(1,1, pC);
-        
-        wsp->GetCollectionPoint(0,0, pM);
-        vtkMath::Subtract(pM,pC,pM1);
-        wsp->GetCollectionPoint(0,3, pM);
-        vtkMath::Subtract(pM,pC,pM2);
-        vtkMath::Cross(pM1,pM2,pM);
-        n2[0] = pM[0];
-        n2[1] = pM[1];
-        n2[2] = pM[2];
+    double pC[3];
+    double pM1[3];
+    double pM2[3];
+    double n2[3];
+    n2[0] = 0;
+    n2[1] = 0;
+    n2[2] = 0;
+    // Collection 0 with 4 points
+    // Collection 1 with 3 points
+    // Collection 2 with 4 points
+    wsp->GetCollectionPoint(1,1, pC);
+    
+    wsp->GetCollectionPoint(0,0, pM);
+    vtkMath::Subtract(pM,pC,pM1);
+    wsp->GetCollectionPoint(0,3, pM);
+    vtkMath::Subtract(pM,pC,pM2);
+    vtkMath::Cross(pM1,pM2,pM);
+    n2[0] = pM[0];
+    n2[1] = pM[1];
+    n2[2] = pM[2];
 
-        wsp->GetCollectionPoint(0,3, pM);
-        vtkMath::Subtract(pM,pC,pM1);
-        wsp->GetCollectionPoint(2,3, pM);
-        vtkMath::Subtract(pM,pC,pM2);
-        vtkMath::Cross(pM1,pM2,pM);
-        n2[0] = n2[0] + pM[0];
-        n2[1] = n2[1] + pM[1];
-        n2[2] = n2[2] + pM[2];
+    wsp->GetCollectionPoint(0,3, pM);
+    vtkMath::Subtract(pM,pC,pM1);
+    wsp->GetCollectionPoint(2,3, pM);
+    vtkMath::Subtract(pM,pC,pM2);
+    vtkMath::Cross(pM1,pM2,pM);
+    n2[0] = n2[0] + pM[0];
+    n2[1] = n2[1] + pM[1];
+    n2[2] = n2[2] + pM[2];
 
-        wsp->GetCollectionPoint(2,3, pM);
-        vtkMath::Subtract(pM,pC,pM1);
-        wsp->GetCollectionPoint(2,0, pM);
-        vtkMath::Subtract(pM,pC,pM2);
-        vtkMath::Cross(pM1,pM2,pM);
-        n2[0] = n2[0] + pM[0];
-        n2[1] = n2[1] + pM[1];
-        n2[2] = n2[2] + pM[2];
-        
-        wsp->GetCollectionPoint(2,0, pM);
-        vtkMath::Subtract(pM,pC,pM1);
-        wsp->GetCollectionPoint(0,0, pM);
-        vtkMath::Subtract(pM,pC,pM2);
-        vtkMath::Cross(pM1,pM2,pM);
-        n2[0] = n2[0] + pM[0];
-        n2[1] = n2[1] + pM[1];
-        n2[2] = n2[2] + pM[2];
-        
-        n2[0] = n2[0] / 4;
-        n2[1] = n2[1] / 4;
-        n2[2] = n2[2] / 4;
-        
+    wsp->GetCollectionPoint(2,3, pM);
+    vtkMath::Subtract(pM,pC,pM1);
+    wsp->GetCollectionPoint(2,0, pM);
+    vtkMath::Subtract(pM,pC,pM2);
+    vtkMath::Cross(pM1,pM2,pM);
+    n2[0] = n2[0] + pM[0];
+    n2[1] = n2[1] + pM[1];
+    n2[2] = n2[2] + pM[2];
+    
+    wsp->GetCollectionPoint(2,0, pM);
+    vtkMath::Subtract(pM,pC,pM1);
+    wsp->GetCollectionPoint(0,0, pM);
+    vtkMath::Subtract(pM,pC,pM2);
+    vtkMath::Cross(pM1,pM2,pM);
+    n2[0] = n2[0] + pM[0];
+    n2[1] = n2[1] + pM[1];
+    n2[2] = n2[2] + pM[2];
+    
+    n2[0] = n2[0] / 4;
+    n2[1] = n2[1] / 4;
+    n2[2] = n2[2] / 4;
+    
 //        3. Calcular el angulo entre V1 y V2
-        double angle = vtkMath::AngleBetweenVectors(n1,n2) * 180 / vtkMath::Pi();
+    double angle = vtkMath::AngleBetweenVectors(n1,n2) * 180 / vtkMath::Pi();
 //        4. Si el angulo es major de 90 Invertir las normales de la superficie actual
-        if (angle<90)
-        {
-            wsp->InvertLstPoints_();
-        } // if angle
-        
-        // --- Finish ---
-        wsp->SetOutputBox();
-        wsp->UndoRedo_SaveCollection();
-    } else {
-            printf("EED ShowNPoints_Tools::CreatePatch_4points  Warning patch not apply. Need juste one group with four points\n");
-    } // if
+    if (angle<90)
+    {
+        wsp->InvertLstPoints_();
+    } // if angle
+    
+    // --- Finish ---
+    wsp->SetOutputBox();
+    wsp->UndoRedo_SaveCollection();
 }
 
 
diff --git a/bbtk/src/bbcreaMaracasVisuShowNPoints_Tools.h b/bbtk/src/bbcreaMaracasVisuShowNPoints_Tools.h
index 54f6b5d..28b8e65 100644
--- a/bbtk/src/bbcreaMaracasVisuShowNPoints_Tools.h
+++ b/bbtk/src/bbcreaMaracasVisuShowNPoints_Tools.h
@@ -35,6 +35,7 @@ class bbcreaMaracasVisu_EXPORT ShowNPoints_Tools
     
     void CreatePatch_3points();
     void CreatePatch_4points();
+    void CreatePatch_Points(std::vector<int> lstX, std::vector<int> lstY, std::vector<int> lstZ);
     void NearestPointToMesh( vtkPoints *points, vtkStaticPointLocator   *pointLocator, double *spc , double *p , double *pM   );
 
 //=====