LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/dxf - ogrdxf_ocstransformer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 105 106 99.1 %
Date: 2024-11-21 22:18:42 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  DXF Translator
       4             :  * Purpose:  Implements the OCS to WCS transformer used in DXF files.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
       9             :  * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  * Copyright (c) 2018, Alan Thomas <alant@outlook.com.au>
      11             :  *
      12             :  * SPDX-License-Identifier: MIT
      13             :  ****************************************************************************/
      14             : 
      15             : #include "ogr_dxf.h"
      16             : 
      17             : /************************************************************************/
      18             : /*                         Mathematical helpers                         */
      19             : /************************************************************************/
      20             : 
      21          63 : static double Det2x2(double a, double b, double c, double d)
      22             : {
      23          63 :     return a * d - b * c;
      24             : }
      25             : 
      26        3868 : static void CrossProduct(const double *a, const double *b, double *vResult)
      27             : {
      28        3868 :     vResult[0] = a[1] * b[2] - a[2] * b[1];
      29        3868 :     vResult[1] = a[2] * b[0] - a[0] * b[2];
      30        3868 :     vResult[2] = a[0] * b[1] - a[1] * b[0];
      31        3868 : }
      32             : 
      33        5802 : static void Scale2Unit(double *adfV)
      34             : {
      35             :     double dfLen =
      36        5802 :         sqrt(adfV[0] * adfV[0] + adfV[1] * adfV[1] + adfV[2] * adfV[2]);
      37        5802 :     if (dfLen != 0)
      38             :     {
      39        5802 :         adfV[0] /= dfLen;
      40        5802 :         adfV[1] /= dfLen;
      41        5802 :         adfV[2] /= dfLen;
      42             :     }
      43        5802 : }
      44             : 
      45             : /************************************************************************/
      46             : /*                        OGRDXFOCSTransformer()                        */
      47             : /************************************************************************/
      48             : 
      49        1934 : OGRDXFOCSTransformer::OGRDXFOCSTransformer(double adfNIn[3],
      50        1934 :                                            bool bInverse /* = false */)
      51       40614 :     : aadfInverse()
      52             : {
      53             :     static const double dSmall = 1.0 / 64.0;
      54             :     static const double adfWZ[3] = {0.0, 0.0, 1.0};
      55             :     static const double adfWY[3] = {0.0, 1.0, 0.0};
      56             : 
      57        1934 :     dfDeterminant = 0.0;
      58        1934 :     Scale2Unit(adfNIn);
      59        1934 :     memcpy(adfN, adfNIn, sizeof(double) * 3);
      60             : 
      61        1934 :     if ((std::abs(adfN[0]) < dSmall) && (std::abs(adfN[1]) < dSmall))
      62        1871 :         CrossProduct(adfWY, adfN, adfAX);
      63             :     else
      64          63 :         CrossProduct(adfWZ, adfN, adfAX);
      65             : 
      66        1934 :     Scale2Unit(adfAX);
      67        1934 :     CrossProduct(adfN, adfAX, adfAY);
      68        1934 :     Scale2Unit(adfAY);
      69             : 
      70        1934 :     if (bInverse == true)
      71             :     {
      72           7 :         const double a[4] = {0.0, adfAX[0], adfAY[0], adfN[0]};
      73           7 :         const double b[4] = {0.0, adfAX[1], adfAY[1], adfN[1]};
      74           7 :         const double c[4] = {0.0, adfAX[2], adfAY[2], adfN[2]};
      75             : 
      76           7 :         dfDeterminant = a[1] * b[2] * c[3] - a[1] * b[3] * c[2] +
      77           7 :                         a[2] * b[3] * c[1] - a[2] * b[1] * c[3] +
      78           7 :                         a[3] * b[1] * c[2] - a[3] * b[2] * c[1];
      79             : 
      80           7 :         if (dfDeterminant != 0.0)
      81             :         {
      82           7 :             const double k = 1.0 / dfDeterminant;
      83           7 :             const double a11 = adfAX[0];
      84           7 :             const double a12 = adfAY[0];
      85           7 :             const double a13 = adfN[0];
      86           7 :             const double a21 = adfAX[1];
      87           7 :             const double a22 = adfAY[1];
      88           7 :             const double a23 = adfN[1];
      89           7 :             const double a31 = adfAX[2];
      90           7 :             const double a32 = adfAY[2];
      91           7 :             const double a33 = adfN[2];
      92             : 
      93           7 :             aadfInverse[1][1] = k * Det2x2(a22, a23, a32, a33);
      94           7 :             aadfInverse[1][2] = k * Det2x2(a13, a12, a33, a32);
      95           7 :             aadfInverse[1][3] = k * Det2x2(a12, a13, a22, a23);
      96             : 
      97           7 :             aadfInverse[2][1] = k * Det2x2(a23, a21, a33, a31);
      98           7 :             aadfInverse[2][2] = k * Det2x2(a11, a13, a31, a33);
      99           7 :             aadfInverse[2][3] = k * Det2x2(a13, a11, a23, a21);
     100             : 
     101           7 :             aadfInverse[3][1] = k * Det2x2(a21, a22, a31, a32);
     102           7 :             aadfInverse[3][2] = k * Det2x2(a12, a11, a32, a31);
     103           7 :             aadfInverse[3][3] = k * Det2x2(a11, a12, a21, a22);
     104             :         }
     105             :     }
     106        1934 : }
     107             : 
     108             : /************************************************************************/
     109             : /*                            Transform()                               */
     110             : /************************************************************************/
     111             : 
     112        1961 : int OGRDXFOCSTransformer::Transform(size_t nCount, double *adfX, double *adfY,
     113             :                                     double *adfZ, double * /* adfT */,
     114             :                                     int *pabSuccess /* = nullptr */)
     115             : {
     116       13525 :     for (size_t i = 0; i < nCount; i++)
     117             :     {
     118       11564 :         const double x = adfX[i];
     119       11564 :         const double y = adfY[i];
     120       11564 :         const double z = adfZ[i];
     121             : 
     122       11564 :         adfX[i] = x * adfAX[0] + y * adfAY[0] + z * adfN[0];
     123       11564 :         adfY[i] = x * adfAX[1] + y * adfAY[1] + z * adfN[1];
     124       11564 :         adfZ[i] = x * adfAX[2] + y * adfAY[2] + z * adfN[2];
     125             : 
     126       11564 :         if (pabSuccess)
     127       11564 :             pabSuccess[i] = TRUE;
     128             :     }
     129        1961 :     return TRUE;
     130             : }
     131             : 
     132             : /************************************************************************/
     133             : /*                          InverseTransform()                          */
     134             : /************************************************************************/
     135             : 
     136          14 : int OGRDXFOCSTransformer::InverseTransform(size_t nCount, double *adfX,
     137             :                                            double *adfY, double *adfZ)
     138             : {
     139          14 :     if (dfDeterminant == 0.0)
     140           0 :         return FALSE;
     141             : 
     142          28 :     for (size_t i = 0; i < nCount; i++)
     143             :     {
     144          14 :         const double x = adfX[i];
     145          14 :         const double y = adfY[i];
     146          14 :         const double z = adfZ[i];
     147             : 
     148          14 :         adfX[i] = x * aadfInverse[1][1] + y * aadfInverse[1][2] +
     149          14 :                   z * aadfInverse[1][3];
     150          14 :         adfY[i] = x * aadfInverse[2][1] + y * aadfInverse[2][2] +
     151          14 :                   z * aadfInverse[2][3];
     152          14 :         adfZ[i] = x * aadfInverse[3][1] + y * aadfInverse[3][2] +
     153          14 :                   z * aadfInverse[3][3];
     154             :     }
     155          14 :     return TRUE;
     156             : }
     157             : 
     158             : /************************************************************************/
     159             : /*                             ComposeOnto()                            */
     160             : /*                                                                      */
     161             : /*    Applies this transformer to the given affine transformer.         */
     162             : /************************************************************************/
     163             : 
     164           3 : void OGRDXFOCSTransformer::ComposeOnto(OGRDXFAffineTransform &oCT) const
     165             : {
     166             :     double adfNew[12];
     167             : 
     168           3 :     adfNew[0] = adfAX[0] * oCT.adfData[0] + adfAY[0] * oCT.adfData[1] +
     169           3 :                 adfN[0] * oCT.adfData[2];
     170           3 :     adfNew[1] = adfAX[1] * oCT.adfData[0] + adfAY[1] * oCT.adfData[1] +
     171           3 :                 adfN[1] * oCT.adfData[2];
     172           3 :     adfNew[2] = adfAX[2] * oCT.adfData[0] + adfAY[2] * oCT.adfData[1] +
     173           3 :                 adfN[2] * oCT.adfData[2];
     174             : 
     175           3 :     adfNew[3] = adfAX[0] * oCT.adfData[3] + adfAY[0] * oCT.adfData[4] +
     176           3 :                 adfN[0] * oCT.adfData[5];
     177           3 :     adfNew[4] = adfAX[1] * oCT.adfData[3] + adfAY[1] * oCT.adfData[4] +
     178           3 :                 adfN[1] * oCT.adfData[5];
     179           3 :     adfNew[5] = adfAX[2] * oCT.adfData[3] + adfAY[2] * oCT.adfData[4] +
     180           3 :                 adfN[2] * oCT.adfData[5];
     181             : 
     182           3 :     adfNew[6] = adfAX[0] * oCT.adfData[6] + adfAY[0] * oCT.adfData[7] +
     183           3 :                 adfN[0] * oCT.adfData[8];
     184           3 :     adfNew[7] = adfAX[1] * oCT.adfData[6] + adfAY[1] * oCT.adfData[7] +
     185           3 :                 adfN[1] * oCT.adfData[8];
     186           3 :     adfNew[8] = adfAX[2] * oCT.adfData[6] + adfAY[2] * oCT.adfData[7] +
     187           3 :                 adfN[2] * oCT.adfData[8];
     188             : 
     189           3 :     adfNew[9] = adfAX[0] * oCT.adfData[9] + adfAY[0] * oCT.adfData[10] +
     190           3 :                 adfN[0] * oCT.adfData[11];
     191           3 :     adfNew[10] = adfAX[1] * oCT.adfData[9] + adfAY[1] * oCT.adfData[10] +
     192           3 :                  adfN[1] * oCT.adfData[11];
     193           3 :     adfNew[11] = adfAX[2] * oCT.adfData[9] + adfAY[2] * oCT.adfData[10] +
     194           3 :                  adfN[2] * oCT.adfData[11];
     195             : 
     196           3 :     memcpy(oCT.adfData, adfNew, sizeof(adfNew));
     197           3 : }

Generated by: LCOV version 1.14