<commit_before>/*! \file tracking.hpp
 \brief The Object and Feature Tracking
 */

/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#ifndef __OPENCV_TRACKING_HPP__
#define __OPENCV_TRACKING_HPP__

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc_c.h"

#ifdef __cplusplus
extern "C" {
#endif

/****************************************************************************************\
*                                  Motion Analysis                                       *
\****************************************************************************************/

/************************************ optical flow ***************************************/

#define  CV_LKFLOW_PYR_A_READY       1
#define  CV_LKFLOW_PYR_B_READY       2
#define  CV_LKFLOW_INITIAL_GUESSES   4
#define  CV_LKFLOW_GET_MIN_EIGENVALS 8

/* It is Lucas & Kanade method, modified to use pyramids.
   Also it does several iterations to get optical flow for
   every point at every pyramid level.
   Calculates optical flow between two images for certain set of points (i.e.
   it is a "sparse" optical flow, which is opposite to the previous 3 methods) */
CVAPI(void)  cvCalcOpticalFlowPyrLK( const CvArr*  prev, const CvArr*  curr,
                                     CvArr*  prev_pyr, CvArr*  curr_pyr,
                                     const CvPoint2D32f* prev_features,
                                     CvPoint2D32f* curr_features,
                                     int       count,
                                     CvSize    win_size,
                                     int       level,
                                     char*     status,
                                     float*    track_error,
                                     CvTermCriteria criteria,
                                     int       flags );

/* Modification of a previous sparse optical flow algorithm to calculate
   affine flow */
CVAPI(void)  cvCalcAffineFlowPyrLK( const CvArr*  prev, const CvArr*  curr,
                                    CvArr*  prev_pyr, CvArr*  curr_pyr,
                                    const CvPoint2D32f* prev_features,
                                    CvPoint2D32f* curr_features,
                                    float* matrices, int  count,
                                    CvSize win_size, int  level,
                                    char* status, float* track_error,
                                    CvTermCriteria criteria, int flags );

/* Estimate rigid transformation between 2 images or 2 point sets */
CVAPI(int)  cvEstimateRigidTransform( const CvArr* A, const CvArr* B,
                                      CvMat* M, int full_affine );

/* Estimate optical flow for each pixel using the two-frame G. Farneback algorithm */
CVAPI(void) cvCalcOpticalFlowFarneback( const CvArr* prev, const CvArr* next,
                                        CvArr* flow, double pyr_scale, int levels,
                                        int winsize, int iterations, int poly_n,
                                        double poly_sigma, int flags );

/********************************* motion templates *************************************/

/****************************************************************************************\
*        All the motion template functions work only with single channel images.         *
*        Silhouette image must have depth IPL_DEPTH_8U or IPL_DEPTH_8S                   *
*        Motion history image must have depth IPL_DEPTH_32F,                             *
*        Gradient mask - IPL_DEPTH_8U or IPL_DEPTH_8S,                                   *
*        Motion orientation image - IPL_DEPTH_32F                                        *
*        Segmentation mask - IPL_DEPTH_32F                                               *
*        All the angles are in degrees, all the times are in milliseconds                *
\****************************************************************************************/

/* Updates motion history image given motion silhouette */
CVAPI(void)    cvUpdateMotionHistory( const CvArr* silhouette, CvArr* mhi,
                                      double timestamp, double duration );

/* Calculates gradient of the motion history image and fills
   a mask indicating where the gradient is valid */
CVAPI(void)    cvCalcMotionGradient( const CvArr* mhi, CvArr* mask, CvArr* orientation,
                                     double delta1, double delta2,
                                     int aperture_size CV_DEFAULT(3));

/* Calculates average motion direction within a selected motion region
   (region can be selected by setting ROIs and/or by composing a valid gradient mask
   with the region mask) */
CVAPI(double)  cvCalcGlobalOrientation( const CvArr* orientation, const CvArr* mask,
                                        const CvArr* mhi, double timestamp,
                                        double duration );

/* Splits a motion history image into a few parts corresponding to separate independent motions
   (e.g. left hand, right hand) */
CVAPI(CvSeq*)  cvSegmentMotion( const CvArr* mhi, CvArr* seg_mask,
                                CvMemStorage* storage,
                                double timestamp, double seg_thresh );

/****************************************************************************************\
*                                       Tracking                                         *
\****************************************************************************************/

/* Implements CAMSHIFT algorithm - determines object position, size and orientation
   from the object histogram back project (extension of meanshift) */
CVAPI(int)  cvCamShift( const CvArr* prob_image, CvRect  window,
                        CvTermCriteria criteria, CvConnectedComp* comp,
                        CvBox2D* box CV_DEFAULT(NULL) );

/* Implements MeanShift algorithm - determines object position
   from the object histogram back project */
CVAPI(int)  cvMeanShift( const CvArr* prob_image, CvRect  window,
                         CvTermCriteria criteria, CvConnectedComp* comp );

/*
standard Kalman filter (in G. Welch' and G. Bishop's notation):

  x(k)=A*x(k-1)+B*u(k)+w(k)  p(w)~N(0,Q)
  z(k)=H*x(k)+v(k),   p(v)~N(0,R)
*/
typedef struct CvKalman
{
    int MP;                     /* number of measurement vector dimensions */
    int DP;                     /* number of state vector dimensions */
    int CP;                     /* number of control vector dimensions */

    /* backward compatibility fields */
#if 1
    float* PosterState;         /* =state_pre->data.fl */
    float* PriorState;          /* =state_post->data.fl */
    float* DynamMatr;           /* =transition_matrix->data.fl */
    float* MeasurementMatr;     /* =measurement_matrix->data.fl */
    float* MNCovariance;        /* =measurement_noise_cov->data.fl */
    float* PNCovariance;        /* =process_noise_cov->data.fl */
    float* KalmGainMatr;        /* =gain->data.fl */
    float* PriorErrorCovariance;/* =error_cov_pre->data.fl */
    float* PosterErrorCovariance;/* =error_cov_post->data.fl */
    float* Temp1;               /* temp1->data.fl */
    float* Temp2;               /* temp2->data.fl */
#endif

    CvMat* state_pre;           /* predicted state (x'(k)):
                                    x(k)=A*x(k-1)+B*u(k) */
    CvMat* state_post;          /* corrected state (x(k)):
                                    x(k)=x'(k)+K(k)*(z(k)-H*x'(k)) */
    CvMat* transition_matrix;   /* state transition matrix (A) */
    CvMat* control_matrix;      /* control matrix (B)
                                   (it is not used if there is no control)*/
    CvMat* measurement_matrix;  /* measurement matrix (H) */
    CvMat* process_noise_cov;   /* process noise covariance matrix (Q) */
    CvMat* measurement_noise_cov; /* measurement noise covariance matrix (R) */
    CvMat* error_cov_pre;       /* priori error estimate covariance matrix (P'(k)):
                                    P'(k)=A*P(k-1)*At + Q)*/
    CvMat* gain;                /* Kalman gain matrix (K(k)):
                                    K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R)*/
    CvMat* error_cov_post;      /* posteriori error estimate covariance matrix (P(k)):
                                    P(k)=(I-K(k)*H)*P'(k) */
    CvMat* temp1;               /* temporary matrices */
    CvMat* temp2;
    CvMat* temp3;
    CvMat* temp4;
    CvMat* temp5;
} CvKalman;

/* Creates Kalman filter and sets A, B, Q, R and state to some initial values */
CVAPI(CvKalman*) cvCreateKalman( int dynam_params, int measure_params,
                                 int control_params CV_DEFAULT(0));

/* Releases Kalman filter state */
CVAPI(void)  cvReleaseKalman( CvKalman** kalman);

/* Updates Kalman filter by time (predicts future state of the system) */
CVAPI(const CvMat*)  cvKalmanPredict( CvKalman* kalman,
                                      const CvMat* control CV_DEFAULT(NULL));

/* Updates Kalman filter by measurement
   (corrects state of the system and internal matrices) */
CVAPI(const CvMat*)  cvKalmanCorrect( CvKalman* kalman, const CvMat* measurement );

#define cvKalmanUpdateByTime  cvKalmanPredict
#define cvKalmanUpdateByMeasurement cvKalmanCorrect

#ifdef __cplusplus
}

namespace cv
{

//! updates motion history image using the current silhouette
CV_EXPORTS_W void updateMotionHistory( InputArray silhouette, InputOutputArray mhi,
                                       double timestamp, double duration );

//! computes the motion gradient orientation image from the motion history image
CV_EXPORTS_W void calcMotionGradient( InputArray mhi, OutputArray mask,
                                      OutputArray orientation,
                                      double delta1, double delta2,
                                      int apertureSize=3 );

//! computes the global orientation of the selected motion history image part
CV_EXPORTS_W double calcGlobalOrientation( InputArray orientation, InputArray mask,
                                           InputArray mhi, double timestamp,
                                           double duration );

CV_EXPORTS_W void segmentMotion(InputArray mhi, OutputArray segmask,
                                CV_OUT vector<Rect>& boundingRects,
                                double timestamp, double segThresh);

//! updates the object tracking window using CAMSHIFT algorithm
CV_EXPORTS_W RotatedRect CamShift( InputArray probImage, CV_OUT CV_IN_OUT Rect& window,
                                   TermCriteria criteria );

//! updates the object tracking window using meanshift algorithm
CV_EXPORTS_W int meanShift( InputArray probImage, CV_OUT CV_IN_OUT Rect& window,
                            TermCriteria criteria );

/*!
 Kalman filter.

 The class implements standard Kalman filter \url{http://en.wikipedia.org/wiki/Kalman_filter}.
 However, you can modify KalmanFilter::transitionMatrix, KalmanFilter::controlMatrix and
 KalmanFilter::measurementMatrix to get the extended Kalman filter functionality.
*/
class CV_EXPORTS_W KalmanFilter
{
public:
    //! the default constructor
    CV_WRAP KalmanFilter();
    //! the full constructor taking the dimensionality of the state, of the measurement and of the control vector
    CV_WRAP KalmanFilter(int dynamParams, int measureParams, int controlParams=0, int type=CV_32F);
    //! re-initializes Kalman filter. The previous content is destroyed.
    void init(int dynamParams, int measureParams, int controlParams=0, int type=CV_32F);

    //! computes predicted state
    CV_WRAP const Mat& predict(const Mat& control=Mat());
    //! updates the predicted state from the measurement
    CV_WRAP const Mat& correct(const Mat& measurement);

    Mat statePre;           //!< predicted state (x'(k)): x(k)=A*x(k-1)+B*u(k)
    Mat statePost;          //!< corrected state (x(k)): x(k)=x'(k)+K(k)*(z(k)-H*x'(k))
    Mat transitionMatrix;   //!< state transition matrix (A)
    Mat controlMatrix;      //!< control matrix (B) (not used if there is no control)
    Mat measurementMatrix;  //!< measurement matrix (H)
    Mat processNoiseCov;    //!< process noise covariance matrix (Q)
    Mat measurementNoiseCov;//!< measurement noise covariance matrix (R)
    Mat errorCovPre;        //!< priori error estimate covariance matrix (P'(k)): P'(k)=A*P(k-1)*At + Q)*/
    Mat gain;               //!< Kalman gain matrix (K(k)): K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R)
    Mat errorCovPost;       //!< posteriori error estimate covariance matrix (P(k)): P(k)=(I-K(k)*H)*P'(k)

    // temporary matrices
    Mat temp1;
    Mat temp2;
    Mat temp3;
    Mat temp4;
    Mat temp5;
};

enum { OPTFLOW_USE_INITIAL_FLOW=4, OPTFLOW_FARNEBACK_GAUSSIAN=256 };

//! computes sparse optical flow using multi-scale Lucas-Kanade algorithm
CV_EXPORTS_W void calcOpticalFlowPyrLK( InputArray prevImg, InputArray nextImg,
                           InputArray prevPts, CV_OUT InputOutputArray nextPts,
                           OutputArray status, OutputArray err,
                           Size winSize=Size(21,21), int maxLevel=3,
                           TermCriteria criteria=TermCriteria(
                            TermCriteria::COUNT+TermCriteria::EPS,
                            30, 0.01),
                           int flags=0,
                           double minEigThreshold=1e-4);

//! computes dense optical flow using Farneback algorithm
CV_EXPORTS_W void calcOpticalFlowFarneback( InputArray prev, InputArray next,
                           CV_OUT InputOutputArray flow, double pyr_scale, int levels, int winsize,
                           int iterations, int poly_n, double poly_sigma, int flags );

//! estimates the best-fit Euqcidean, similarity, affine or perspective transformation
// that maps one 2D point set to another or one image to another.
CV_EXPORTS_W Mat estimateRigidTransform( InputArray src, InputArray dst,
                                         bool fullAffine);

}

#endif

#endif
<commit_msg>Added OPTFLOW_LK_GET_MIN_EIGENVALS flag as alias for CV_LKFLOW_GET_MIN_EIGENVALS.<commit_after>/*! \file tracking.hpp
 \brief The Object and Feature Tracking
 */

/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#ifndef __OPENCV_TRACKING_HPP__
#define __OPENCV_TRACKING_HPP__

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc_c.h"

#ifdef __cplusplus
extern "C" {
#endif

/****************************************************************************************\
*                                  Motion Analysis                                       *
\****************************************************************************************/

/************************************ optical flow ***************************************/

#define  CV_LKFLOW_PYR_A_READY       1
#define  CV_LKFLOW_PYR_B_READY       2
#define  CV_LKFLOW_INITIAL_GUESSES   4
#define  CV_LKFLOW_GET_MIN_EIGENVALS 8

/* It is Lucas & Kanade method, modified to use pyramids.
   Also it does several iterations to get optical flow for
   every point at every pyramid level.
   Calculates optical flow between two images for certain set of points (i.e.
   it is a "sparse" optical flow, which is opposite to the previous 3 methods) */
CVAPI(void)  cvCalcOpticalFlowPyrLK( const CvArr*  prev, const CvArr*  curr,
                                     CvArr*  prev_pyr, CvArr*  curr_pyr,
                                     const CvPoint2D32f* prev_features,
                                     CvPoint2D32f* curr_features,
                                     int       count,
                                     CvSize    win_size,
                                     int       level,
                                     char*     status,
                                     float*    track_error,
                                     CvTermCriteria criteria,
                                     int       flags );

/* Modification of a previous sparse optical flow algorithm to calculate
   affine flow */
CVAPI(void)  cvCalcAffineFlowPyrLK( const CvArr*  prev, const CvArr*  curr,
                                    CvArr*  prev_pyr, CvArr*  curr_pyr,
                                    const CvPoint2D32f* prev_features,
                                    CvPoint2D32f* curr_features,
                                    float* matrices, int  count,
                                    CvSize win_size, int  level,
                                    char* status, float* track_error,
                                    CvTermCriteria criteria, int flags );

/* Estimate rigid transformation between 2 images or 2 point sets */
CVAPI(int)  cvEstimateRigidTransform( const CvArr* A, const CvArr* B,
                                      CvMat* M, int full_affine );

/* Estimate optical flow for each pixel using the two-frame G. Farneback algorithm */
CVAPI(void) cvCalcOpticalFlowFarneback( const CvArr* prev, const CvArr* next,
                                        CvArr* flow, double pyr_scale, int levels,
                                        int winsize, int iterations, int poly_n,
                                        double poly_sigma, int flags );

/********************************* motion templates *************************************/

/****************************************************************************************\
*        All the motion template functions work only with single channel images.         *
*        Silhouette image must have depth IPL_DEPTH_8U or IPL_DEPTH_8S                   *
*        Motion history image must have depth IPL_DEPTH_32F,                             *
*        Gradient mask - IPL_DEPTH_8U or IPL_DEPTH_8S,                                   *
*        Motion orientation image - IPL_DEPTH_32F                                        *
*        Segmentation mask - IPL_DEPTH_32F                                               *
*        All the angles are in degrees, all the times are in milliseconds                *
\****************************************************************************************/

/* Updates motion history image given motion silhouette */
CVAPI(void)    cvUpdateMotionHistory( const CvArr* silhouette, CvArr* mhi,
                                      double timestamp, double duration );

/* Calculates gradient of the motion history image and fills
   a mask indicating where the gradient is valid */
CVAPI(void)    cvCalcMotionGradient( const CvArr* mhi, CvArr* mask, CvArr* orientation,
                                     double delta1, double delta2,
                                     int aperture_size CV_DEFAULT(3));

/* Calculates average motion direction within a selected motion region
   (region can be selected by setting ROIs and/or by composing a valid gradient mask
   with the region mask) */
CVAPI(double)  cvCalcGlobalOrientation( const CvArr* orientation, const CvArr* mask,
                                        const CvArr* mhi, double timestamp,
                                        double duration );

/* Splits a motion history image into a few parts corresponding to separate independent motions
   (e.g. left hand, right hand) */
CVAPI(CvSeq*)  cvSegmentMotion( const CvArr* mhi, CvArr* seg_mask,
                                CvMemStorage* storage,
                                double timestamp, double seg_thresh );

/****************************************************************************************\
*                                       Tracking                                         *
\****************************************************************************************/

/* Implements CAMSHIFT algorithm - determines object position, size and orientation
   from the object histogram back project (extension of meanshift) */
CVAPI(int)  cvCamShift( const CvArr* prob_image, CvRect  window,
                        CvTermCriteria criteria, CvConnectedComp* comp,
                        CvBox2D* box CV_DEFAULT(NULL) );

/* Implements MeanShift algorithm - determines object position
   from the object histogram back project */
CVAPI(int)  cvMeanShift( const CvArr* prob_image, CvRect  window,
                         CvTermCriteria criteria, CvConnectedComp* comp );

/*
standard Kalman filter (in G. Welch' and G. Bishop's notation):

  x(k)=A*x(k-1)+B*u(k)+w(k)  p(w)~N(0,Q)
  z(k)=H*x(k)+v(k),   p(v)~N(0,R)
*/
typedef struct CvKalman
{
    int MP;                     /* number of measurement vector dimensions */
    int DP;                     /* number of state vector dimensions */
    int CP;                     /* number of control vector dimensions */

    /* backward compatibility fields */
#if 1
    float* PosterState;         /* =state_pre->data.fl */
    float* PriorState;          /* =state_post->data.fl */
    float* DynamMatr;           /* =transition_matrix->data.fl */
    float* MeasurementMatr;     /* =measurement_matrix->data.fl */
    float* MNCovariance;        /* =measurement_noise_cov->data.fl */
    float* PNCovariance;        /* =process_noise_cov->data.fl */
    float* KalmGainMatr;        /* =gain->data.fl */
    float* PriorErrorCovariance;/* =error_cov_pre->data.fl */
    float* PosterErrorCovariance;/* =error_cov_post->data.fl */
    float* Temp1;               /* temp1->data.fl */
    float* Temp2;               /* temp2->data.fl */
#endif

    CvMat* state_pre;           /* predicted state (x'(k)):
                                    x(k)=A*x(k-1)+B*u(k) */
    CvMat* state_post;          /* corrected state (x(k)):
                                    x(k)=x'(k)+K(k)*(z(k)-H*x'(k)) */
    CvMat* transition_matrix;   /* state transition matrix (A) */
    CvMat* control_matrix;      /* control matrix (B)
                                   (it is not used if there is no control)*/
    CvMat* measurement_matrix;  /* measurement matrix (H) */
    CvMat* process_noise_cov;   /* process noise covariance matrix (Q) */
    CvMat* measurement_noise_cov; /* measurement noise covariance matrix (R) */
    CvMat* error_cov_pre;       /* priori error estimate covariance matrix (P'(k)):
                                    P'(k)=A*P(k-1)*At + Q)*/
    CvMat* gain;                /* Kalman gain matrix (K(k)):
                                    K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R)*/
    CvMat* error_cov_post;      /* posteriori error estimate covariance matrix (P(k)):
                                    P(k)=(I-K(k)*H)*P'(k) */
    CvMat* temp1;               /* temporary matrices */
    CvMat* temp2;
    CvMat* temp3;
    CvMat* temp4;
    CvMat* temp5;
} CvKalman;

/* Creates Kalman filter and sets A, B, Q, R and state to some initial values */
CVAPI(CvKalman*) cvCreateKalman( int dynam_params, int measure_params,
                                 int control_params CV_DEFAULT(0));

/* Releases Kalman filter state */
CVAPI(void)  cvReleaseKalman( CvKalman** kalman);

/* Updates Kalman filter by time (predicts future state of the system) */
CVAPI(const CvMat*)  cvKalmanPredict( CvKalman* kalman,
                                      const CvMat* control CV_DEFAULT(NULL));

/* Updates Kalman filter by measurement
   (corrects state of the system and internal matrices) */
CVAPI(const CvMat*)  cvKalmanCorrect( CvKalman* kalman, const CvMat* measurement );

#define cvKalmanUpdateByTime  cvKalmanPredict
#define cvKalmanUpdateByMeasurement cvKalmanCorrect

#ifdef __cplusplus
}

namespace cv
{

//! updates motion history image using the current silhouette
CV_EXPORTS_W void updateMotionHistory( InputArray silhouette, InputOutputArray mhi,
                                       double timestamp, double duration );

//! computes the motion gradient orientation image from the motion history image
CV_EXPORTS_W void calcMotionGradient( InputArray mhi, OutputArray mask,
                                      OutputArray orientation,
                                      double delta1, double delta2,
                                      int apertureSize=3 );

//! computes the global orientation of the selected motion history image part
CV_EXPORTS_W double calcGlobalOrientation( InputArray orientation, InputArray mask,
                                           InputArray mhi, double timestamp,
                                           double duration );

CV_EXPORTS_W void segmentMotion(InputArray mhi, OutputArray segmask,
                                CV_OUT vector<Rect>& boundingRects,
                                double timestamp, double segThresh);

//! updates the object tracking window using CAMSHIFT algorithm
CV_EXPORTS_W RotatedRect CamShift( InputArray probImage, CV_OUT CV_IN_OUT Rect& window,
                                   TermCriteria criteria );

//! updates the object tracking window using meanshift algorithm
CV_EXPORTS_W int meanShift( InputArray probImage, CV_OUT CV_IN_OUT Rect& window,
                            TermCriteria criteria );

/*!
 Kalman filter.

 The class implements standard Kalman filter \url{http://en.wikipedia.org/wiki/Kalman_filter}.
 However, you can modify KalmanFilter::transitionMatrix, KalmanFilter::controlMatrix and
 KalmanFilter::measurementMatrix to get the extended Kalman filter functionality.
*/
class CV_EXPORTS_W KalmanFilter
{
public:
    //! the default constructor
    CV_WRAP KalmanFilter();
    //! the full constructor taking the dimensionality of the state, of the measurement and of the control vector
    CV_WRAP KalmanFilter(int dynamParams, int measureParams, int controlParams=0, int type=CV_32F);
    //! re-initializes Kalman filter. The previous content is destroyed.
    void init(int dynamParams, int measureParams, int controlParams=0, int type=CV_32F);

    //! computes predicted state
    CV_WRAP const Mat& predict(const Mat& control=Mat());
    //! updates the predicted state from the measurement
    CV_WRAP const Mat& correct(const Mat& measurement);

    Mat statePre;           //!< predicted state (x'(k)): x(k)=A*x(k-1)+B*u(k)
    Mat statePost;          //!< corrected state (x(k)): x(k)=x'(k)+K(k)*(z(k)-H*x'(k))
    Mat transitionMatrix;   //!< state transition matrix (A)
    Mat controlMatrix;      //!< control matrix (B) (not used if there is no control)
    Mat measurementMatrix;  //!< measurement matrix (H)
    Mat processNoiseCov;    //!< process noise covariance matrix (Q)
    Mat measurementNoiseCov;//!< measurement noise covariance matrix (R)
    Mat errorCovPre;        //!< priori error estimate covariance matrix (P'(k)): P'(k)=A*P(k-1)*At + Q)*/
    Mat gain;               //!< Kalman gain matrix (K(k)): K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R)
    Mat errorCovPost;       //!< posteriori error estimate covariance matrix (P(k)): P(k)=(I-K(k)*H)*P'(k)

    // temporary matrices
    Mat temp1;
    Mat temp2;
    Mat temp3;
    Mat temp4;
    Mat temp5;
};

enum
{
    OPTFLOW_USE_INITIAL_FLOW = CV_LKFLOW_INITIAL_GUESSES,
    OPTFLOW_LK_GET_MIN_EIGENVALS = CV_LKFLOW_GET_MIN_EIGENVALS,
    OPTFLOW_FARNEBACK_GAUSSIAN = 256
};

//! computes sparse optical flow using multi-scale Lucas-Kanade algorithm
CV_EXPORTS_W void calcOpticalFlowPyrLK( InputArray prevImg, InputArray nextImg,
                           InputArray prevPts, CV_OUT InputOutputArray nextPts,
                           OutputArray status, OutputArray err,
                           Size winSize=Size(21,21), int maxLevel=3,
                           TermCriteria criteria=TermCriteria(
                            TermCriteria::COUNT+TermCriteria::EPS,
                            30, 0.01),
                           int flags=0,
                           double minEigThreshold=1e-4);

//! computes dense optical flow using Farneback algorithm
CV_EXPORTS_W void calcOpticalFlowFarneback( InputArray prev, InputArray next,
                           CV_OUT InputOutputArray flow, double pyr_scale, int levels, int winsize,
                           int iterations, int poly_n, double poly_sigma, int flags );

//! estimates the best-fit Euqcidean, similarity, affine or perspective transformation
// that maps one 2D point set to another or one image to another.
CV_EXPORTS_W Mat estimateRigidTransform( InputArray src, InputArray dst,
                                         bool fullAffine);

}

#endif

#endif
<|endoftext|>


<commit_before>/*-------------------------------------------------------------------------
 *
 *   FILE
 *	connectionitf.cxx
 *
 *   DESCRIPTION
 *      implementation of the pqxx::ConnectionItf abstract base class.
 *   pqxx::ConnectionItf encapsulates a frontend to backend connection
 *
 * Copyright (c) 2001-2003, Jeroen T. Vermeulen <jtv@xs4all.nl>
 *
 *-------------------------------------------------------------------------
 */
#include <algorithm>
#include <cstdio>
#include <stdexcept>

#include "pqxx/connectionitf.h"
#include "pqxx/result.h"
#include "pqxx/transaction.h"
#include "pqxx/trigger.h"

using namespace PGSTD;

namespace
{

// Keep track of a pointer to be free()d automatically.
// Ownership policy is simple: object dies when PQAlloc object's value does.
template<typename T> class PQAlloc
{
  T *m_Obj;
public:
  PQAlloc() : m_Obj(0) {}
  explicit PQAlloc(T *obj) : m_Obj(obj) {}
  ~PQAlloc() { close(); }

  PQAlloc &operator=(T *obj) throw ()
  {
    if (obj != m_Obj)
    {
      close();
      m_Obj = obj;
    }
    return *this;
  }

  operator bool() const throw () { return m_Obj != 0; }
  bool operator!() const throw () { return !m_Obj; }

  T *operator->() const
  {
    if (!m_Obj) throw logic_error("Null pointer dereferenced");
    return m_Obj;
  }

  T &operator*() const { return *operator->(); }

  T *c_ptr() const throw () { return m_Obj; }

  void close() throw () { if (m_Obj) freemem(); m_Obj = 0; }

  void freemem() throw ()
  {
#ifdef HAVE_PQFREEMEM
    PQfreemem(m_Obj);
#else
    free(m_Obj);
#endif
  }

private:
  PQAlloc(const PQAlloc &);		// Not allowed
  PQAlloc &operator=(const PQAlloc &);	// Not allowed
};
}

extern "C"
{
// Pass C-linkage notice processor call on to C++-linkage Noticer object.  The
// void * argument points to the Noticer.
void pqxxNoticeCaller(void *arg, const char *Msg)
{
  if (arg && Msg) (*static_cast<pqxx::Noticer *>(arg))(Msg);
}
}

pqxx::ConnectionItf::ConnectionItf(const string &ConnInfo) :
  m_ConnInfo(ConnInfo),
  m_Conn(0),
  m_Trans(),
  m_Noticer(),
  m_Trace(0)
{
}

pqxx::ConnectionItf::ConnectionItf(const char ConnInfo[]) :
  m_ConnInfo(ConnInfo ? ConnInfo : ""),
  m_Conn(0),
  m_Trans(),
  m_Noticer(),
  m_Trace(0)
{
}

void pqxx::ConnectionItf::Connect() const
{
  if (m_Conn) throw logic_error("libqxx internal error: spurious Connect()");

  m_Conn = PQconnectdb(m_ConnInfo.c_str());

  if (!m_Conn)
    throw broken_connection();

  if (!is_open())
  {
    const string Msg( ErrMsg() );
    Disconnect();
    throw broken_connection(Msg);
  }

  if (Status() != CONNECTION_OK)
  {
    const string Msg( ErrMsg() );
    Disconnect();
    throw runtime_error(Msg);
  }

  SetupState();
}

void pqxx::ConnectionItf::Deactivate() const
{
  if (m_Conn)
  {
    if (m_Trans.get())
      throw logic_error("Attempt to deactivate connection while transaction "
	                "'" + m_Trans.get()->Name() + "' "
			"still open");

    Disconnect();
  }
}

void pqxx::ConnectionItf::SetClientEncoding(const char Encoding[])
{
  if (PQsetClientEncoding(m_Conn, Encoding) != 0)
    throw runtime_error("Could not set client encoding to " +
	                string(Encoding));
}

/** Set up various parts of logical connection state that may need to be
 * recovered because the physical connection to the database was lost and is
 * being reset, or that may not have been initialized yet.
 */
void pqxx::ConnectionItf::SetupState() const
{
  if (!m_Conn)
    throw logic_error("libpqxx internal error: SetupState() on no connection");

  if (m_Noticer.get())
    PQsetNoticeProcessor(m_Conn, pqxxNoticeCaller, m_Noticer.get());

  InternalSetTrace();

  // Reinstate all active triggers
  if (!m_Triggers.empty())
  {
    const TriggerList::const_iterator End = m_Triggers.end();
    string Last;
    for (TriggerList::const_iterator i = m_Triggers.begin(); i != End; ++i)
    {
      // m_Triggers can handle multiple Triggers waiting on the same event;
      // issue just one LISTEN for each event.
      if (i->first != Last)
      {
        Result R( PQexec(m_Conn, ("LISTEN " + i->first).c_str()) );
        R.CheckStatus();
        Last = i->first;
      }
    }
  }
}

void pqxx::ConnectionItf::Disconnect() const throw ()
{
  if (m_Conn)
  {
    PQfinish(m_Conn);
    m_Conn = 0;
  }
}

bool pqxx::ConnectionItf::is_open() const
{
  return m_Conn && (Status() != CONNECTION_BAD);
}

auto_ptr<pqxx::Noticer>
pqxx::ConnectionItf::SetNoticer(auto_ptr<pqxx::Noticer> N)
{
  if (N.get()) PQsetNoticeProcessor(m_Conn, pqxxNoticeCaller, N.get());
  else PQsetNoticeProcessor(m_Conn, 0, 0);

  auto_ptr<Noticer> Old = m_Noticer;
  // TODO: Can this line fail?  If yes, we'd be killing Old prematurely...
  m_Noticer = N;

  return Old;
}

void pqxx::ConnectionItf::ProcessNotice(const char msg[]) throw ()
{
  if (msg)
  {
    // TODO: Find cleaner solution for default case!
    if (m_Noticer.get()) (*m_Noticer.get())(msg);
    else fputs(msg, stderr);
  }
}

void pqxx::ConnectionItf::Trace(FILE *Out)
{
  m_Trace = Out;
  if (m_Conn) InternalSetTrace();
}

void pqxx::ConnectionItf::AddTrigger(pqxx::Trigger *T)
{
  if (!T) throw invalid_argument("Null trigger registered");

  // Add to triggers list and attempt to start listening.
  const TriggerList::iterator p = m_Triggers.find(T->Name());
  const TriggerList::value_type NewVal(T->Name(), T);

  if (m_Conn && (p == m_Triggers.end()))
  {
    // Not listening on this event yet, start doing so.
    //
    Result R( PQexec(m_Conn, ("LISTEN " + string(T->Name())).c_str()) );

    try
    {
      R.CheckStatus();
    }
    catch (const broken_connection &)
    {
    }
    catch (const exception &)
    {
      if (is_open()) throw;
    }
    m_Triggers.insert(NewVal);
  }
  else
  {
    m_Triggers.insert(p, NewVal);
  }

}

void pqxx::ConnectionItf::RemoveTrigger(pqxx::Trigger *T) throw ()
{
  if (!T) return;

  try
  {
    // Keep Sun compiler happy...  Hope it doesn't annoy other compilers
    pair<const string, Trigger *> tmp_pair(T->Name(), T);
    TriggerList::value_type E = tmp_pair;

    typedef pair<TriggerList::iterator, TriggerList::iterator> Range;
    Range R = m_Triggers.equal_range(E.first);

    const TriggerList::iterator i = find(R.first, R.second, E);

    if (i == R.second)
    {
      ProcessNotice("Attempt to remove unknown trigger '" +
		    E.first +
		    "'");
    }
    else
    {
      if (m_Conn && (R.second == ++R.first))
	PQexec(m_Conn, ("UNLISTEN " + string(T->Name())).c_str());

      m_Triggers.erase(i);
    }
  }
  catch (const exception &e)
  {
    ProcessNotice(e.what());
  }
}

void pqxx::ConnectionItf::GetNotifs()
{
  if (!m_Conn) return;

  PQconsumeInput(m_Conn);

  // Even if somehow we receive notifications during our transaction, don't
  // deliver them.
  if (m_Trans.get()) return;

  for (PQAlloc<PGnotify> N( PQnotifies(m_Conn) ); N; N = PQnotifies(m_Conn))
  {
    typedef TriggerList::iterator TI;

    pair<TI, TI> Hit = m_Triggers.equal_range(string(N->relname));
    for (TI i = Hit.first; i != Hit.second; ++i)
      try
      {
        (*i->second)(N->be_pid);
      }
      catch (const exception &e)
      {
	ProcessNotice("Exception in trigger handler '" +
		      i->first +
		      "': " +
		      e.what() +
		      "\n");
      }

    N.close();
  }
}

const char *pqxx::ConnectionItf::ErrMsg() const
{
  return m_Conn ? PQerrorMessage(m_Conn) : "No connection to database";
}

pqxx::Result pqxx::ConnectionItf::Exec(const char Query[],
                                       int Retries,
				       const char OnReconnect[])
{
  Activate();

  Result R( PQexec(m_Conn, Query) );

  while ((Retries > 0) && !R && !is_open())
  {
    Retries--;

    Reset(OnReconnect);
    if (is_open()) R = PQexec(m_Conn, Query);
  }

  if (!R) throw broken_connection();
  R.CheckStatus();

  GetNotifs();

  return R;
}

void pqxx::ConnectionItf::Reset(const char OnReconnect[])
{
  // Attempt to set up or restore connection
  if (!m_Conn) Connect();
  else
  {
    PQreset(m_Conn);
    SetupState();

    // Perform any extra patchup work involved in restoring the connection,
    // typically set up a transaction.
    if (OnReconnect)
    {
      Result Temp( PQexec(m_Conn, OnReconnect) );
      Temp.CheckStatus();
    }
  }
}

void pqxx::ConnectionItf::close() throw ()
{
  try
  {
    if (m_Trans.get())
      ProcessNotice("Closing connection while transaction '" +
		    m_Trans.get()->Name() +
		    "' still open\n");

    if (!m_Triggers.empty())
    {
      string T;
      for (TriggerList::const_iterator i = m_Triggers.begin();
	   i != m_Triggers.end();
	   ++i)
	T += " " + i->first;

        ProcessNotice("Closing connection with outstanding triggers:" +
	              T +
		      "\n");
      m_Triggers.clear();
    }

    Disconnect();
  }
  catch (...)
  {
  }
}

void pqxx::ConnectionItf::InternalSetTrace() const
{
  if (m_Trace) PQtrace(m_Conn, m_Trace);
  else PQuntrace(m_Conn);
}

void pqxx::ConnectionItf::RegisterTransaction(const TransactionItf *T)
{
  m_Trans.Register(T);
}

void pqxx::ConnectionItf::UnregisterTransaction(const TransactionItf *T) throw ()
{
  try
  {
    m_Trans.Unregister(T);
  }
  catch (const exception &e)
  {
    ProcessNotice(string(e.what()) + "\n");
  }
}

void pqxx::ConnectionItf::MakeEmpty(pqxx::Result &R, ExecStatusType Stat)
{
  if (!m_Conn)
    throw logic_error("Internal libpqxx error: MakeEmpty() on null connection");

  R = Result(PQmakeEmptyPGresult(m_Conn, Stat));
}

void pqxx::ConnectionItf::BeginCopyRead(const string &Table)
{
  Result R( Exec(("COPY " + Table + " TO STDOUT").c_str()) );
  R.CheckStatus();
}

bool pqxx::ConnectionItf::ReadCopyLine(string &Line)
{
  if (!m_Conn)
    throw logic_error("Internal libpqxx error: "
	              "ReadCopyLine() on null connection");

  char Buf[256];
  bool LineComplete = false;

  Line.erase();

  while (!LineComplete)
  {
    switch (PQgetline(m_Conn, Buf, sizeof(Buf)))
    {
    case EOF:
      throw runtime_error("Unexpected EOF from backend");

    case 0:
      LineComplete = true;
      break;

    case 1:
      break;

    default:
      throw runtime_error("Unexpected COPY response from backend");
    }

    Line += Buf;
  }

  bool Result = (Line != "\\.");

  if (!Result) Line.erase();

  return Result;
}

void pqxx::ConnectionItf::BeginCopyWrite(const string &Table)
{
  Result R( Exec(("COPY " + Table + " FROM STDIN").c_str()) );
  R.CheckStatus();
}

void pqxx::ConnectionItf::WriteCopyLine(const string &Line)
{
  if (!m_Conn)
    throw logic_error("Internal libpqxx error: "
	              "WriteCopyLine() on null connection");

  PQputline(m_Conn, (Line + "\n").c_str());
}

// End COPY operation.  Careful: this assumes that no more lines remain to be
// read or written, and the COPY operation has been properly terminated with a
// line containing only the two characters "\."
void pqxx::ConnectionItf::EndCopy()
{
  if (PQendcopy(m_Conn) != 0) throw runtime_error(ErrMsg());
}

<commit_msg>Made less confusing to doxygen<commit_after>/*-------------------------------------------------------------------------
 *
 *   FILE
 *	connectionitf.cxx
 *
 *   DESCRIPTION
 *      implementation of the pqxx::ConnectionItf abstract base class.
 *   pqxx::ConnectionItf encapsulates a frontend to backend connection
 *
 * Copyright (c) 2001-2003, Jeroen T. Vermeulen <jtv@xs4all.nl>
 *
 *-------------------------------------------------------------------------
 */
#include <algorithm>
#include <cstdio>
#include <stdexcept>

#include "pqxx/connectionitf.h"
#include "pqxx/result.h"
#include "pqxx/transaction.h"
#include "pqxx/trigger.h"

using namespace PGSTD;

namespace
{

// Keep track of a pointer to be free()d automatically.
// Ownership policy is simple: object dies when PQAlloc object's value does.
template<typename T> class PQAlloc
{
  T *m_Obj;
public:
  PQAlloc() : m_Obj(0) {}
  explicit PQAlloc(T *obj) : m_Obj(obj) {}
  ~PQAlloc() { close(); }

  PQAlloc &operator=(T *obj) throw ()
  {
    if (obj != m_Obj)
    {
      close();
      m_Obj = obj;
    }
    return *this;
  }

  operator bool() const throw () { return m_Obj != 0; }
  bool operator!() const throw () { return !m_Obj; }

  T *operator->() const
  {
    if (!m_Obj) throw logic_error("Null pointer dereferenced");
    return m_Obj;
  }

  T &operator*() const { return *operator->(); }

  T *c_ptr() const throw () { return m_Obj; }

  void close() throw () { if (m_Obj) freemem(); m_Obj = 0; }

  void freemem() throw ()
  {
#ifdef HAVE_PQFREEMEM
    PQfreemem(m_Obj);
#else
    free(m_Obj);
#endif
  }

private:
  PQAlloc(const PQAlloc &);		// Not allowed
  PQAlloc &operator=(const PQAlloc &);	// Not allowed
};
}

extern "C"
{
// Pass C-linkage notice processor call on to C++-linkage Noticer object.  The
// void * argument points to the Noticer.
void pqxxNoticeCaller(void *arg, const char *Msg)
{
  if (arg && Msg) (*static_cast<pqxx::Noticer *>(arg))(Msg);
}
}

pqxx::ConnectionItf::ConnectionItf(const string &ConnInfo) :
  m_ConnInfo(ConnInfo),
  m_Conn(0),
  m_Trans(),
  m_Noticer(),
  m_Trace(0)
{
}

pqxx::ConnectionItf::ConnectionItf(const char ConnInfo[]) :
  m_ConnInfo(ConnInfo ? ConnInfo : ""),
  m_Conn(0),
  m_Trans(),
  m_Noticer(),
  m_Trace(0)
{
}

void pqxx::ConnectionItf::Connect() const
{
  if (m_Conn) throw logic_error("libqxx internal error: spurious Connect()");

  m_Conn = PQconnectdb(m_ConnInfo.c_str());

  if (!m_Conn)
    throw broken_connection();

  if (!is_open())
  {
    const string Msg( ErrMsg() );
    Disconnect();
    throw broken_connection(Msg);
  }

  if (Status() != CONNECTION_OK)
  {
    const string Msg( ErrMsg() );
    Disconnect();
    throw runtime_error(Msg);
  }

  SetupState();
}

void pqxx::ConnectionItf::Deactivate() const
{
  if (m_Conn)
  {
    if (m_Trans.get())
      throw logic_error("Attempt to deactivate connection while transaction "
	                "'" + m_Trans.get()->Name() + "' "
			"still open");

    Disconnect();
  }
}

void pqxx::ConnectionItf::SetClientEncoding(const char Encoding[])
{
  if (PQsetClientEncoding(m_Conn, Encoding) != 0)
    throw runtime_error("Could not set client encoding to " +
	                string(Encoding));
}

/** Set up various parts of logical connection state that may need to be
 * recovered because the physical connection to the database was lost and is
 * being reset, or that may not have been initialized yet.
 */
void pqxx::ConnectionItf::SetupState() const
{
  if (!m_Conn)
    throw logic_error("libpqxx internal error: SetupState() on no connection");

  if (m_Noticer.get())
    PQsetNoticeProcessor(m_Conn, pqxxNoticeCaller, m_Noticer.get());

  InternalSetTrace();

  // Reinstate all active triggers
  if (!m_Triggers.empty())
  {
    const TriggerList::const_iterator End = m_Triggers.end();
    string Last;
    for (TriggerList::const_iterator i = m_Triggers.begin(); i != End; ++i)
    {
      // m_Triggers can handle multiple Triggers waiting on the same event;
      // issue just one LISTEN for each event.
      if (i->first != Last)
      {
        Result R( PQexec(m_Conn, ("LISTEN " + i->first).c_str()) );
        R.CheckStatus();
        Last = i->first;
      }
    }
  }
}

void pqxx::ConnectionItf::Disconnect() const throw ()
{
  if (m_Conn)
  {
    PQfinish(m_Conn);
    m_Conn = 0;
  }
}

bool pqxx::ConnectionItf::is_open() const
{
  return m_Conn && (Status() != CONNECTION_BAD);
}

auto_ptr<Noticer>
pqxx::ConnectionItf::SetNoticer(auto_ptr<Noticer> N)
{
  if (N.get()) PQsetNoticeProcessor(m_Conn, pqxxNoticeCaller, N.get());
  else PQsetNoticeProcessor(m_Conn, 0, 0);

  auto_ptr<Noticer> Old = m_Noticer;
  // TODO: Can this line fail?  If yes, we'd be killing Old prematurely...
  m_Noticer = N;

  return Old;
}

void pqxx::ConnectionItf::ProcessNotice(const char msg[]) throw ()
{
  if (msg)
  {
    // TODO: Find cleaner solution for default case!
    if (m_Noticer.get()) (*m_Noticer.get())(msg);
    else fputs(msg, stderr);
  }
}

void pqxx::ConnectionItf::Trace(FILE *Out)
{
  m_Trace = Out;
  if (m_Conn) InternalSetTrace();
}

void pqxx::ConnectionItf::AddTrigger(pqxx::Trigger *T)
{
  if (!T) throw invalid_argument("Null trigger registered");

  // Add to triggers list and attempt to start listening.
  const TriggerList::iterator p = m_Triggers.find(T->Name());
  const TriggerList::value_type NewVal(T->Name(), T);

  if (m_Conn && (p == m_Triggers.end()))
  {
    // Not listening on this event yet, start doing so.
    //
    Result R( PQexec(m_Conn, ("LISTEN " + string(T->Name())).c_str()) );

    try
    {
      R.CheckStatus();
    }
    catch (const broken_connection &)
    {
    }
    catch (const exception &)
    {
      if (is_open()) throw;
    }
    m_Triggers.insert(NewVal);
  }
  else
  {
    m_Triggers.insert(p, NewVal);
  }

}

void pqxx::ConnectionItf::RemoveTrigger(pqxx::Trigger *T) throw ()
{
  if (!T) return;

  try
  {
    // Keep Sun compiler happy...  Hope it doesn't annoy other compilers
    pair<const string, Trigger *> tmp_pair(T->Name(), T);
    TriggerList::value_type E = tmp_pair;

    typedef pair<TriggerList::iterator, TriggerList::iterator> Range;
    Range R = m_Triggers.equal_range(E.first);

    const TriggerList::iterator i = find(R.first, R.second, E);

    if (i == R.second)
    {
      ProcessNotice("Attempt to remove unknown trigger '" +
		    E.first +
		    "'");
    }
    else
    {
      if (m_Conn && (R.second == ++R.first))
	PQexec(m_Conn, ("UNLISTEN " + string(T->Name())).c_str());

      m_Triggers.erase(i);
    }
  }
  catch (const exception &e)
  {
    ProcessNotice(e.what());
  }
}

void pqxx::ConnectionItf::GetNotifs()
{
  if (!m_Conn) return;

  PQconsumeInput(m_Conn);

  // Even if somehow we receive notifications during our transaction, don't
  // deliver them.
  if (m_Trans.get()) return;

  for (PQAlloc<PGnotify> N( PQnotifies(m_Conn) ); N; N = PQnotifies(m_Conn))
  {
    typedef TriggerList::iterator TI;

    pair<TI, TI> Hit = m_Triggers.equal_range(string(N->relname));
    for (TI i = Hit.first; i != Hit.second; ++i)
      try
      {
        (*i->second)(N->be_pid);
      }
      catch (const exception &e)
      {
	ProcessNotice("Exception in trigger handler '" +
		      i->first +
		      "': " +
		      e.what() +
		      "\n");
      }

    N.close();
  }
}

const char *pqxx::ConnectionItf::ErrMsg() const
{
  return m_Conn ? PQerrorMessage(m_Conn) : "No connection to database";
}

pqxx::Result pqxx::ConnectionItf::Exec(const char Query[],
                                       int Retries,
				       const char OnReconnect[])
{
  Activate();

  Result R( PQexec(m_Conn, Query) );

  while ((Retries > 0) && !R && !is_open())
  {
    Retries--;

    Reset(OnReconnect);
    if (is_open()) R = PQexec(m_Conn, Query);
  }

  if (!R) throw broken_connection();
  R.CheckStatus();

  GetNotifs();

  return R;
}

void pqxx::ConnectionItf::Reset(const char OnReconnect[])
{
  // Attempt to set up or restore connection
  if (!m_Conn) Connect();
  else
  {
    PQreset(m_Conn);
    SetupState();

    // Perform any extra patchup work involved in restoring the connection,
    // typically set up a transaction.
    if (OnReconnect)
    {
      Result Temp( PQexec(m_Conn, OnReconnect) );
      Temp.CheckStatus();
    }
  }
}

void pqxx::ConnectionItf::close() throw ()
{
  try
  {
    if (m_Trans.get())
      ProcessNotice("Closing connection while transaction '" +
		    m_Trans.get()->Name() +
		    "' still open\n");

    if (!m_Triggers.empty())
    {
      string T;
      for (TriggerList::const_iterator i = m_Triggers.begin();
	   i != m_Triggers.end();
	   ++i)
	T += " " + i->first;

        ProcessNotice("Closing connection with outstanding triggers:" +
	              T +
		      "\n");
      m_Triggers.clear();
    }

    Disconnect();
  }
  catch (...)
  {
  }
}

void pqxx::ConnectionItf::InternalSetTrace() const
{
  if (m_Trace) PQtrace(m_Conn, m_Trace);
  else PQuntrace(m_Conn);
}

void pqxx::ConnectionItf::RegisterTransaction(const TransactionItf *T)
{
  m_Trans.Register(T);
}

void pqxx::ConnectionItf::UnregisterTransaction(const TransactionItf *T) throw ()
{
  try
  {
    m_Trans.Unregister(T);
  }
  catch (const exception &e)
  {
    ProcessNotice(string(e.what()) + "\n");
  }
}

void pqxx::ConnectionItf::MakeEmpty(pqxx::Result &R, ExecStatusType Stat)
{
  if (!m_Conn)
    throw logic_error("Internal libpqxx error: MakeEmpty() on null connection");

  R = Result(PQmakeEmptyPGresult(m_Conn, Stat));
}

void pqxx::ConnectionItf::BeginCopyRead(const string &Table)
{
  Result R( Exec(("COPY " + Table + " TO STDOUT").c_str()) );
  R.CheckStatus();
}

bool pqxx::ConnectionItf::ReadCopyLine(string &Line)
{
  if (!m_Conn)
    throw logic_error("Internal libpqxx error: "
	              "ReadCopyLine() on null connection");

  char Buf[256];
  bool LineComplete = false;

  Line.erase();

  while (!LineComplete)
  {
    switch (PQgetline(m_Conn, Buf, sizeof(Buf)))
    {
    case EOF:
      throw runtime_error("Unexpected EOF from backend");

    case 0:
      LineComplete = true;
      break;

    case 1:
      break;

    default:
      throw runtime_error("Unexpected COPY response from backend");
    }

    Line += Buf;
  }

  bool Result = (Line != "\\.");

  if (!Result) Line.erase();

  return Result;
}

void pqxx::ConnectionItf::BeginCopyWrite(const string &Table)
{
  Result R( Exec(("COPY " + Table + " FROM STDIN").c_str()) );
  R.CheckStatus();
}

void pqxx::ConnectionItf::WriteCopyLine(const string &Line)
{
  if (!m_Conn)
    throw logic_error("Internal libpqxx error: "
	              "WriteCopyLine() on null connection");

  PQputline(m_Conn, (Line + "\n").c_str());
}

// End COPY operation.  Careful: this assumes that no more lines remain to be
// read or written, and the COPY operation has been properly terminated with a
// line containing only the two characters "\."
void pqxx::ConnectionItf::EndCopy()
{
  if (PQendcopy(m_Conn) != 0) throw runtime_error(ErrMsg());
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DAVProperties.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 16:06:28 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    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.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _DAVPROPERTIES_HXX_
#define _DAVPROPERTIES_HXX_

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif
#ifndef _NEONTYPES_HXX_
#include "NeonTypes.hxx"
#endif

namespace webdav_ucp
{

struct DAVProperties
{
    static const ::rtl::OUString CREATIONDATE;
    static const ::rtl::OUString DISPLAYNAME;
    static const ::rtl::OUString GETCONTENTLANGUAGE;
    static const ::rtl::OUString GETCONTENTLENGTH;
    static const ::rtl::OUString GETCONTENTTYPE;
    static const ::rtl::OUString GETETAG;
    static const ::rtl::OUString GETLASTMODIFIED;
    static const ::rtl::OUString LOCKDISCOVERY;
    static const ::rtl::OUString RESOURCETYPE;
    static const ::rtl::OUString SOURCE;
    static const ::rtl::OUString SUPPORTEDLOCK;
    static const ::rtl::OUString EXECUTABLE;

    static void createNeonPropName( const rtl::OUString & rFullName,
                                    NeonPropName & rName );
    static void createUCBPropName ( const char * nspace,
                                    const char * name,
                                    rtl::OUString & rFullName );

    static bool isUCBDeadProperty( const NeonPropName & rName );
};

}; // namespace webdav_ucp

#endif // _DAVPROPERTIES_HXX_
<commit_msg>INTEGRATION: CWS warnings01 (1.3.10); FILE MERGED 2005/11/10 18:10:16 pl 1.3.10.1: #i55991# removed warnings<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DAVProperties.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 05:33:29 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    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.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _DAVPROPERTIES_HXX_
#define _DAVPROPERTIES_HXX_

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif
#ifndef _NEONTYPES_HXX_
#include "NeonTypes.hxx"
#endif

namespace webdav_ucp
{

struct DAVProperties
{
    static const ::rtl::OUString CREATIONDATE;
    static const ::rtl::OUString DISPLAYNAME;
    static const ::rtl::OUString GETCONTENTLANGUAGE;
    static const ::rtl::OUString GETCONTENTLENGTH;
    static const ::rtl::OUString GETCONTENTTYPE;
    static const ::rtl::OUString GETETAG;
    static const ::rtl::OUString GETLASTMODIFIED;
    static const ::rtl::OUString LOCKDISCOVERY;
    static const ::rtl::OUString RESOURCETYPE;
    static const ::rtl::OUString SOURCE;
    static const ::rtl::OUString SUPPORTEDLOCK;
    static const ::rtl::OUString EXECUTABLE;

    static void createNeonPropName( const rtl::OUString & rFullName,
                                    NeonPropName & rName );
    static void createUCBPropName ( const char * nspace,
                                    const char * name,
                                    rtl::OUString & rFullName );

    static bool isUCBDeadProperty( const NeonPropName & rName );
};

} // namespace webdav_ucp

#endif // _DAVPROPERTIES_HXX_
<|endoftext|>


<commit_before>MODULE DevSearch;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- 20070307, bh, caseSens handling in Find corrected
	"
	issues	= ""

**)

	IMPORT
		Kernel, Files, Fonts, Ports, Models, Views, Containers, Dialog, Windows,
		TextModels, TextRulers, TextViews, TextControllers, TextMappers, TextCmds, StdLinks;

	CONST
		N = 32; T = 10;
		maxPat = 64;
		noMatchFoundKey = "#Std:NoMatchFound";
		locationKey = "#Std:Location";
		countKey = "#Std:Count";
		searchingKey = "#Std:Searching";
		openFindCmdKey = "#Dev:OpenFindCmd";
		openFindCmdNotFoundKey = "#Dev:OpenFindCmdNotFound";

	TYPE
		Pattern = ARRAY maxPat OF CHAR;
		Text = POINTER TO RECORD
			next: Text;
			num: INTEGER;
			title: Files.Name
		END;

	VAR
		w: TextMappers.Formatter;

	PROCEDURE Find (t: TextModels.Model; pat: Pattern; title: Files.Name; VAR list: Text; caseSens: BOOLEAN);
		VAR r: TextModels.Reader; num: INTEGER; i, j, b, e, n: INTEGER; ch: CHAR; ref: Pattern; l: Text;
	BEGIN
		n := 0; num := 0;
		WHILE pat[n] # 0X DO
			IF ~caseSens THEN pat[n] := CAP(pat[n]) END ;
			INC(n)
		END;
		r := t.NewReader(NIL);
		r.SetPos(0); r.ReadChar(ch);
		WHILE ~r.eot DO
			ref[0] := ch; i := 0; j := 0; b := 0; e := 1;
			WHILE ~r.eot & (i < n) DO
				IF caseSens & (pat[i]=ch) OR ~caseSens & (pat[i] = CAP(ch)) THEN INC(i); j := (j + 1) MOD maxPat
				ELSE i := 0; b := (b + 1) MOD maxPat; j := b
				END;
				IF j # e THEN ch := ref[j]
				ELSE r.ReadChar(ch); ref[j] := ch; e := (e + 1) MOD maxPat
				END
			END;
			IF i = n THEN INC(num) END
		END;
		IF num > 0 THEN
			NEW(l); l.num := num; l.title := title; l.next := list; list := l
		END
	END Find;

	PROCEDURE List (list: Text; pat: Pattern; source, caseSens: BOOLEAN);
		VAR a0: TextModels.Attributes; cmd: ARRAY 256 OF CHAR; this, t: Text; max: INTEGER;
	BEGIN
		IF list = NIL THEN
			Dialog.MapString(noMatchFoundKey, cmd);
			w.WriteString(cmd)
		ELSE
			a0 := w.rider.attr;
			w.rider.SetAttr(TextModels.NewStyle(w.rider.attr, {Fonts.italic}));
			Dialog.MapString(locationKey, cmd);
			w.WriteString(cmd); w.WriteTab;
			Dialog.MapString(countKey, cmd);
			w.WriteString(cmd); w.WriteLn;
			w.rider.SetAttr(a0);
			REPEAT
				t := list; max := 1; this := NIL;
				WHILE t # NIL DO
					IF t.num >= max THEN max := t.num; this := t END;
					t := t.next
				END;
				IF this # NIL THEN
					w.rider.SetAttr(TextModels.NewStyle(w.rider.attr, {Fonts.underline}));
					w.rider.SetAttr(TextModels.NewColor(w.rider.attr, Ports.blue));
					IF source THEN
						cmd := "StdCmds.OpenDoc('" + this.title + "'); DevSearch.SelectCaseSens('" + pat + "')"
					ELSE
						IF caseSens THEN
							cmd := "StdCmds.OpenBrowser('" + this.title + "', '" + this.title + "'); " +
								"DevSearch.SelectCaseSens('" + pat + "')"
						ELSE
							cmd := "StdCmds.OpenBrowser('" + this.title + "', '" + this.title + "'); " +
								"DevSearch.SelectCaseInSens('" + pat + "')"
						END
					END;
					w.WriteView(StdLinks.dir.NewLink(cmd));
					w.WriteString(this.title);
					w.WriteView(StdLinks.dir.NewLink(""));
					w.rider.SetAttr(a0);
					w.WriteTab; w.WriteInt(this.num); w.WriteLn;
					this.num := 0
				END
			UNTIL this = NIL
		END
	END List;

	PROCEDURE NewRuler (): TextRulers.Ruler;
		CONST mm = Ports.mm;
		VAR p: TextRulers.Prop;
	BEGIN
		NEW(p);
		p.valid := {TextRulers.right, TextRulers.tabs, TextRulers.opts};
		p.opts.val := {TextRulers.rightFixed}; p.opts.mask := p.opts.val;
		p.right := 100 * mm;
		p.tabs.len := 1;
		p.tabs.tab[0].stop := 70 * mm;
		RETURN TextRulers.dir.NewFromProp(p)
	END NewRuler;

	PROCEDURE ThisText (loc: Files.Locator; VAR name: Files.Name): TextModels.Model;
		VAR v: Views.View; m: Models.Model;
	BEGIN
		v := Views.OldView(loc, name);
		IF v # NIL THEN
			m := v.ThisModel();
			IF m # NIL THEN
				WITH m: TextModels.Model DO RETURN m ELSE END
			END
		END;
		RETURN NIL
	END ThisText;

	PROCEDURE Search (source, caseSens: BOOLEAN);
		VAR pat: Pattern; t, log: TextModels.Model; v: Views.View; title: Views.Title; c: Containers.Controller;
			files: Files.FileInfo; dirs: Files.LocInfo;
			loc: Files.Locator; path, p: Files.Name; list: Text;
	BEGIN
		(*TextCmds.InitFindDialog; *)
		pat := TextCmds.find.find$;
		IF pat # "" THEN
			Dialog.ShowStatus(searchingKey);
			TextCmds.find.find := pat$;
			log := TextModels.dir.New();
			w.ConnectTo(log); w.SetPos(0);
			IF source THEN loc := Files.dir.This("Mod"); path := "Mod"
			ELSE loc := Files.dir.This("Docu"); path := "Docu"
			END;
			files := Files.dir.FileList(loc); list := NIL;
			WHILE files # NIL DO
				IF files.type = Kernel.docType THEN
					p := path + "/" + files.name;
					Find(ThisText(loc, files.name), pat, p, list, caseSens)
				END;
				files := files.next
			END;
			loc := Files.dir.This("");
			dirs := Files.dir.LocList(loc);
			WHILE dirs # NIL DO
				loc := Files.dir.This(dirs.name); path := dirs.name + "/";
				IF source THEN loc := loc.This("Mod"); path := path + "Mod"
				ELSE loc := loc.This("Docu"); path := path +"Docu"
				END;
				files := Files.dir.FileList(loc);
				WHILE files # NIL DO
					IF files.type = Kernel.docType THEN
						p := path + "/" + files.name;
						t := ThisText(loc, files.name);
						IF t # NIL THEN
							Find(t, pat, p, list, caseSens)
						END
					END;
					files := files.next
				END;
				dirs := dirs.next
			END;
			List(list, pat, source, caseSens);
			v := TextViews.dir.New(log);
			title := 'Search for "' + pat + '"';
			v(TextViews.View).SetDefaults(NewRuler(), TextViews.dir.defAttr);
			Views.OpenAux(v, title);
			c := v(Containers.View).ThisController();
			c.SetOpts(c.opts + {Containers.noCaret});
			w.ConnectTo(NIL);
			Dialog.ShowStatus("")
		END
	END Search;

	PROCEDURE SearchInSources*;
	BEGIN
		Search(TRUE, TRUE)
	END SearchInSources;

	PROCEDURE SearchInDocu* (opts: ARRAY OF CHAR);
		VAR caseSens: BOOLEAN;
	BEGIN
		caseSens := ~TextCmds.find.ignoreCase;
		IF LEN(opts$) > 0 THEN
			IF CAP(opts[0]) = 'S' THEN
				caseSens := TRUE
			ELSIF CAP(opts[0]) = 'I' THEN
				caseSens := FALSE
			END
		END;
		Search(FALSE, caseSens)
	END SearchInDocu;

	PROCEDURE SelectCaseSens* (pat: ARRAY OF CHAR);
	BEGIN
		TextCmds.find.find := pat$;
		TextCmds.find.ignoreCase := FALSE;
		Dialog.Update(TextCmds.find);
		TextCmds.FindFirst("")
	END SelectCaseSens;

	PROCEDURE SelectCaseInSens* (pat: ARRAY OF CHAR);
		VAR res: INTEGER; cmd: Dialog.String;
	BEGIN
		TextCmds.find.find := pat$;
		TextCmds.find.ignoreCase := TRUE;
		Dialog.Update(TextCmds.find);
		Dialog.MapString(openFindCmdKey, cmd);
		Dialog.Call(cmd, openFindCmdNotFoundKey, res);
		TextCmds.FindFirst("")
	END SelectCaseInSens;

	PROCEDURE NextChar (r: TextModels.Reader): CHAR;
		VAR ch: CHAR;
	BEGIN
		REPEAT r.ReadChar(ch) UNTIL (ch > " ") OR r.eot;
		RETURN ch
	END NextChar;

	PROCEDURE CompTexts (ta, tb: TextModels.Model; VAR sa, sb, ea, eb: INTEGER);
		VAR da, db, d, i, j, p: INTEGER; t: LONGINT; ra, rb: TextModels.Reader;
			cha, chb: CHAR; s: ARRAY N OF CHAR;
	BEGIN
		ra := ta.NewReader(NIL); ra.SetPos(ea);
		rb := tb.NewReader(NIL); rb.SetPos(eb);
		REPEAT
			cha := NextChar(ra); chb := NextChar(rb)
		UNTIL (cha # chb) OR ra.eot OR rb.eot;
		IF ra.eot THEN sa := ra.Pos() ELSE sa := ra.Pos() - 1 END;
		IF rb.eot THEN sb := rb.Pos() ELSE sb := rb.Pos() - 1 END;
		t := Kernel.Time() + T * Kernel.timeResolution;
		da := sa + 1; db := sb + 1; d := 1; j := 0;
		REPEAT
			ea := da;
			IF ea < ta.Length() THEN
				ra.SetPos(ea); s[0] := NextChar(ra);
				da := ra.Pos(); i := 1;
				WHILE i < N DO s[i] := NextChar(ra); INC(i) END;
				i := 0; rb.SetPos(sb);
				REPEAT
					eb := rb.Pos(); chb := NextChar(rb);
					IF chb = s[0] THEN
						p := rb.Pos(); j := 0;
						WHILE (j < N) & (chb = s[j]) DO chb := NextChar(rb); INC(j) END;
						rb.SetPos(p)
					END;
					INC(i)
				UNTIL (j = N) OR (i = d) OR rb.eot
			END;
			INC(d);
			IF j < N THEN
				eb := db;
				IF eb < tb.Length() THEN
					rb.SetPos(eb); s[0] := NextChar(rb);
					db := rb.Pos(); i := 1;
					WHILE i < N DO s[i] := NextChar(rb); INC(i) END;
					i := 0; ra.SetPos(sa);
					REPEAT
						ea := ra.Pos(); cha := NextChar(ra);
						IF cha = s[0] THEN
							p := ra.Pos(); j := 0;
							WHILE (j < N) & (cha = s[j]) DO cha := NextChar(ra); INC(j) END;
							ra.SetPos(p)
						END;
						INC(i)
					UNTIL (j = N) OR (i = d) OR ra.eot
				END
			END
		UNTIL (j = N) OR (ea >= ta.Length()) & (eb >= tb.Length()) OR (Kernel.Time() > t);
		IF j < N THEN ea := ta.Length(); eb := tb.Length() END
	END CompTexts;

	PROCEDURE Compare*;
		VAR wa, wb: Windows.Window; va, vb: Views.View; ca, cb: Containers.Controller; sa, sb, ea, eb: INTEGER;
	BEGIN
		wa := Windows.dir.First();
		IF wa # NIL THEN
			wb := Windows.dir.Next(wa);
			IF wb # NIL THEN
				va := wa.doc.ThisView();
				WITH va: TextViews.View DO
					vb := wb.doc.ThisView();
					WITH vb: TextViews.View DO
						ca := va.ThisController();
						WITH ca: TextControllers.Controller DO
							cb := vb.ThisController();
							WITH cb: TextControllers.Controller DO
								ca.GetSelection(sa, ea);
								IF (* ea = -1 *) sa = ea THEN ea := MAX(0, ca.CaretPos()) END;
								cb.GetSelection(sb, eb);
								IF (* eb = -1 *) sb = eb THEN eb := MAX(0, cb.CaretPos()) END;
								CompTexts(va.ThisModel(), vb.ThisModel(), sa, sb, ea, eb);
								IF ea > sa THEN ca.SetSelection(sa, ea) ELSE ca.SetCaret(sa) END;
								IF eb > sb THEN cb.SetSelection(sb, eb) ELSE cb.SetCaret(sb) END;
								va.ShowRangeIn(Views.ThisFrame(wa.frame, va), sa, ea);
								vb.ShowRangeIn(Views.ThisFrame(wb.frame, vb), sb, eb)
							END
						END
					ELSE
					END
				ELSE
				END
			END
		END
	END Compare;

END DevSearch.
<commit_msg>20150403, center #37, fixing traps with long search patterns in DevSearch<commit_after>MODULE DevSearch;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- 20070307, bh, caseSens handling in Find corrected
	"
	issues	= ""

**)

	IMPORT
		Kernel, Files, Fonts, Ports, Models, Views, Containers, Dialog, Windows,
		TextModels, TextRulers, TextViews, TextControllers, TextMappers, TextCmds, StdLinks;

	CONST
		N = 32; T = 10;
		maxPat = LEN(TextCmds.find.find);
		noMatchFoundKey = "#Std:NoMatchFound";
		locationKey = "#Std:Location";
		countKey = "#Std:Count";
		searchingKey = "#Std:Searching";
		openFindCmdKey = "#Dev:OpenFindCmd";
		openFindCmdNotFoundKey = "#Dev:OpenFindCmdNotFound";

	TYPE
		Pattern = ARRAY maxPat OF CHAR;
		Text = POINTER TO RECORD
			next: Text;
			num: INTEGER;
			title: Files.Name
		END;

	VAR
		w: TextMappers.Formatter;

	PROCEDURE Find (t: TextModels.Model; pat: Pattern; title: Files.Name; VAR list: Text; caseSens: BOOLEAN);
		VAR r: TextModels.Reader; num: INTEGER; i, j, b, e, n: INTEGER; ch: CHAR; ref: Pattern; l: Text;
	BEGIN
		n := 0; num := 0;
		WHILE pat[n] # 0X DO
			IF ~caseSens THEN pat[n] := CAP(pat[n]) END ;
			INC(n)
		END;
		r := t.NewReader(NIL);
		r.SetPos(0); r.ReadChar(ch);
		WHILE ~r.eot DO
			ref[0] := ch; i := 0; j := 0; b := 0; e := 1;
			WHILE ~r.eot & (i < n) DO
				IF caseSens & (pat[i]=ch) OR ~caseSens & (pat[i] = CAP(ch)) THEN INC(i); j := (j + 1) MOD maxPat
				ELSE i := 0; b := (b + 1) MOD maxPat; j := b
				END;
				IF j # e THEN ch := ref[j]
				ELSE r.ReadChar(ch); ref[j] := ch; e := (e + 1) MOD maxPat
				END
			END;
			IF i = n THEN INC(num) END
		END;
		IF num > 0 THEN
			NEW(l); l.num := num; l.title := title; l.next := list; list := l
		END
	END Find;

	PROCEDURE List (list: Text; pat: Pattern; source, caseSens: BOOLEAN);
		VAR a0: TextModels.Attributes; this, t: Text; max: INTEGER;
			cmd: ARRAY maxPat + LEN(t.title) + 50  OF CHAR;
	BEGIN
		IF list = NIL THEN
			Dialog.MapString(noMatchFoundKey, cmd);
			w.WriteString(cmd)
		ELSE
			a0 := w.rider.attr;
			w.rider.SetAttr(TextModels.NewStyle(w.rider.attr, {Fonts.italic}));
			Dialog.MapString(locationKey, cmd);
			w.WriteString(cmd); w.WriteTab;
			Dialog.MapString(countKey, cmd);
			w.WriteString(cmd); w.WriteLn;
			w.rider.SetAttr(a0);
			REPEAT
				t := list; max := 1; this := NIL;
				WHILE t # NIL DO
					IF t.num >= max THEN max := t.num; this := t END;
					t := t.next
				END;
				IF this # NIL THEN
					w.rider.SetAttr(TextModels.NewStyle(w.rider.attr, {Fonts.underline}));
					w.rider.SetAttr(TextModels.NewColor(w.rider.attr, Ports.blue));
					IF source THEN
						cmd := "StdCmds.OpenDoc('" + this.title + "'); DevSearch.SelectCaseSens('" + pat + "')"
					ELSE
						IF caseSens THEN
							cmd := "StdCmds.OpenBrowser('" + this.title + "', '" + this.title + "'); " +
								"DevSearch.SelectCaseSens('" + pat + "')"
						ELSE
							cmd := "StdCmds.OpenBrowser('" + this.title + "', '" + this.title + "'); " +
								"DevSearch.SelectCaseInSens('" + pat + "')"
						END
					END;
					w.WriteView(StdLinks.dir.NewLink(cmd));
					w.WriteString(this.title);
					w.WriteView(StdLinks.dir.NewLink(""));
					w.rider.SetAttr(a0);
					w.WriteTab; w.WriteInt(this.num); w.WriteLn;
					this.num := 0
				END
			UNTIL this = NIL
		END
	END List;

	PROCEDURE NewRuler (): TextRulers.Ruler;
		CONST mm = Ports.mm;
		VAR p: TextRulers.Prop;
	BEGIN
		NEW(p);
		p.valid := {TextRulers.right, TextRulers.tabs, TextRulers.opts};
		p.opts.val := {TextRulers.rightFixed}; p.opts.mask := p.opts.val;
		p.right := 100 * mm;
		p.tabs.len := 1;
		p.tabs.tab[0].stop := 70 * mm;
		RETURN TextRulers.dir.NewFromProp(p)
	END NewRuler;

	PROCEDURE ThisText (loc: Files.Locator; VAR name: Files.Name): TextModels.Model;
		VAR v: Views.View; m: Models.Model;
	BEGIN
		v := Views.OldView(loc, name);
		IF v # NIL THEN
			m := v.ThisModel();
			IF m # NIL THEN
				WITH m: TextModels.Model DO RETURN m ELSE END
			END
		END;
		RETURN NIL
	END ThisText;

	PROCEDURE GetTitle(IN pat: ARRAY OF CHAR; OUT title: Views.Title);
		VAR pos: INTEGER; i, j: INTEGER; ch: CHAR;
	BEGIN
		title := 'Search for "'; i := LEN(title$); j := 0; ch := pat[0];
		WHILE (ch # 0X) & (i < LEN(title) - 2) DO
			IF ch < " " THEN title[i] := " " ELSE title[i] := ch END ; (* replace tabs and line feeds by spaces *)
			INC(i); INC(j); ch := pat[j]
		END ;
		IF ch # 0X THEN title[i - 3] := "."; title[i - 2] := "."; title[i - 1] := "." END ;
		title[i] := '"'; title[i + 1] := 0X
	END GetTitle;

	PROCEDURE Search (source, caseSens: BOOLEAN);
		VAR pat: Pattern; t, log: TextModels.Model; v: Views.View; title: Views.Title; c: Containers.Controller;
			files: Files.FileInfo; dirs: Files.LocInfo;
			loc: Files.Locator; path, p: Files.Name; list: Text;
	BEGIN
		(*TextCmds.InitFindDialog; *)
		pat := TextCmds.find.find$;
		IF pat # "" THEN
			Dialog.ShowStatus(searchingKey);
			TextCmds.find.find := pat$;
			log := TextModels.dir.New();
			w.ConnectTo(log); w.SetPos(0);
			IF source THEN loc := Files.dir.This("Mod"); path := "Mod"
			ELSE loc := Files.dir.This("Docu"); path := "Docu"
			END;
			files := Files.dir.FileList(loc); list := NIL;
			WHILE files # NIL DO
				IF files.type = Kernel.docType THEN
					p := path + "/" + files.name;
					Find(ThisText(loc, files.name), pat, p, list, caseSens)
				END;
				files := files.next
			END;
			loc := Files.dir.This("");
			dirs := Files.dir.LocList(loc);
			WHILE dirs # NIL DO
				loc := Files.dir.This(dirs.name); path := dirs.name + "/";
				IF source THEN loc := loc.This("Mod"); path := path + "Mod"
				ELSE loc := loc.This("Docu"); path := path +"Docu"
				END;
				files := Files.dir.FileList(loc);
				WHILE files # NIL DO
					IF files.type = Kernel.docType THEN
						p := path + "/" + files.name;
						t := ThisText(loc, files.name);
						IF t # NIL THEN
							Find(t, pat, p, list, caseSens)
						END
					END;
					files := files.next
				END;
				dirs := dirs.next
			END;
			List(list, pat, source, caseSens);
			v := TextViews.dir.New(log);
			GetTitle(pat, title);
			v(TextViews.View).SetDefaults(NewRuler(), TextViews.dir.defAttr);
			Views.OpenAux(v, title);
			c := v(Containers.View).ThisController();
			c.SetOpts(c.opts + {Containers.noCaret});
			w.ConnectTo(NIL);
			Dialog.ShowStatus("")
		END
	END Search;

	PROCEDURE SearchInSources*;
	BEGIN
		Search(TRUE, TRUE)
	END SearchInSources;

	PROCEDURE SearchInDocu* (opts: ARRAY OF CHAR);
		VAR caseSens: BOOLEAN;
	BEGIN
		caseSens := ~TextCmds.find.ignoreCase;
		IF LEN(opts$) > 0 THEN
			IF CAP(opts[0]) = 'S' THEN
				caseSens := TRUE
			ELSIF CAP(opts[0]) = 'I' THEN
				caseSens := FALSE
			END
		END;
		Search(FALSE, caseSens)
	END SearchInDocu;

	PROCEDURE SelectCaseSens* (pat: ARRAY OF CHAR);
	BEGIN
		TextCmds.find.find := pat$;
		TextCmds.find.ignoreCase := FALSE;
		Dialog.Update(TextCmds.find);
		TextCmds.FindFirst("")
	END SelectCaseSens;

	PROCEDURE SelectCaseInSens* (pat: ARRAY OF CHAR);
		VAR res: INTEGER; cmd: Dialog.String;
	BEGIN
		TextCmds.find.find := pat$;
		TextCmds.find.ignoreCase := TRUE;
		Dialog.Update(TextCmds.find);
		Dialog.MapString(openFindCmdKey, cmd);
		Dialog.Call(cmd, openFindCmdNotFoundKey, res);
		TextCmds.FindFirst("")
	END SelectCaseInSens;

	PROCEDURE NextChar (r: TextModels.Reader): CHAR;
		VAR ch: CHAR;
	BEGIN
		REPEAT r.ReadChar(ch) UNTIL (ch > " ") OR r.eot;
		RETURN ch
	END NextChar;

	PROCEDURE CompTexts (ta, tb: TextModels.Model; VAR sa, sb, ea, eb: INTEGER);
		VAR da, db, d, i, j, p: INTEGER; t: LONGINT; ra, rb: TextModels.Reader;
			cha, chb: CHAR; s: ARRAY N OF CHAR;
	BEGIN
		ra := ta.NewReader(NIL); ra.SetPos(ea);
		rb := tb.NewReader(NIL); rb.SetPos(eb);
		REPEAT
			cha := NextChar(ra); chb := NextChar(rb)
		UNTIL (cha # chb) OR ra.eot OR rb.eot;
		IF ra.eot THEN sa := ra.Pos() ELSE sa := ra.Pos() - 1 END;
		IF rb.eot THEN sb := rb.Pos() ELSE sb := rb.Pos() - 1 END;
		t := Kernel.Time() + T * Kernel.timeResolution;
		da := sa + 1; db := sb + 1; d := 1; j := 0;
		REPEAT
			ea := da;
			IF ea < ta.Length() THEN
				ra.SetPos(ea); s[0] := NextChar(ra);
				da := ra.Pos(); i := 1;
				WHILE i < N DO s[i] := NextChar(ra); INC(i) END;
				i := 0; rb.SetPos(sb);
				REPEAT
					eb := rb.Pos(); chb := NextChar(rb);
					IF chb = s[0] THEN
						p := rb.Pos(); j := 0;
						WHILE (j < N) & (chb = s[j]) DO chb := NextChar(rb); INC(j) END;
						rb.SetPos(p)
					END;
					INC(i)
				UNTIL (j = N) OR (i = d) OR rb.eot
			END;
			INC(d);
			IF j < N THEN
				eb := db;
				IF eb < tb.Length() THEN
					rb.SetPos(eb); s[0] := NextChar(rb);
					db := rb.Pos(); i := 1;
					WHILE i < N DO s[i] := NextChar(rb); INC(i) END;
					i := 0; ra.SetPos(sa);
					REPEAT
						ea := ra.Pos(); cha := NextChar(ra);
						IF cha = s[0] THEN
							p := ra.Pos(); j := 0;
							WHILE (j < N) & (cha = s[j]) DO cha := NextChar(ra); INC(j) END;
							ra.SetPos(p)
						END;
						INC(i)
					UNTIL (j = N) OR (i = d) OR ra.eot
				END
			END
		UNTIL (j = N) OR (ea >= ta.Length()) & (eb >= tb.Length()) OR (Kernel.Time() > t);
		IF j < N THEN ea := ta.Length(); eb := tb.Length() END
	END CompTexts;

	PROCEDURE Compare*;
		VAR wa, wb: Windows.Window; va, vb: Views.View; ca, cb: Containers.Controller; sa, sb, ea, eb: INTEGER;
	BEGIN
		wa := Windows.dir.First();
		IF wa # NIL THEN
			wb := Windows.dir.Next(wa);
			IF wb # NIL THEN
				va := wa.doc.ThisView();
				WITH va: TextViews.View DO
					vb := wb.doc.ThisView();
					WITH vb: TextViews.View DO
						ca := va.ThisController();
						WITH ca: TextControllers.Controller DO
							cb := vb.ThisController();
							WITH cb: TextControllers.Controller DO
								ca.GetSelection(sa, ea);
								IF (* ea = -1 *) sa = ea THEN ea := MAX(0, ca.CaretPos()) END;
								cb.GetSelection(sb, eb);
								IF (* eb = -1 *) sb = eb THEN eb := MAX(0, cb.CaretPos()) END;
								CompTexts(va.ThisModel(), vb.ThisModel(), sa, sb, ea, eb);
								IF ea > sa THEN ca.SetSelection(sa, ea) ELSE ca.SetCaret(sa) END;
								IF eb > sb THEN cb.SetSelection(sb, eb) ELSE cb.SetCaret(sb) END;
								va.ShowRangeIn(Views.ThisFrame(wa.frame, va), sa, ea);
								vb.ShowRangeIn(Views.ThisFrame(wb.frame, vb), sb, eb)
							END
						END
					ELSE
					END
				ELSE
				END
			END
		END
	END Compare;

END DevSearch.
<|endoftext|>


<commit_before>/*
* Copyright (C) 2017 by Godlike
* This code is licensed under the MIT license (MIT)
* (http://opensource.org/licenses/MIT)
*/

#include <unicorn/video/Primitives.hpp>
#include <unicorn/utility/Logger.hpp>

#include <glm/gtc/constants.hpp>

namespace unicorn
{
namespace video
{
void Primitives::Cube(Mesh& mesh)
{
    std::vector<Vertex> vertices{{
        //front
        {{0.5f, -0.5f, 0.5f},{1.0f, 0.0f}},
        {{0.5f, -0.5f, 0.5f},{0.0f, 0.0f}},
        {{0.5f, -0.5f, 0.5f},{0.0f, 0.0f}},
        {{-0.5f, 0.5f, 0.5f},{1.0f, 1.0f}},

        //right
        {{0.5f, 0.5f, 0.5f},{1.0f, 1.0f}},
        {{0.5f, 0.5f, -0.5f},{0.0f, 1.0f}},
        {{0.5f, -0.5f, -0.5f},{0.0f, 0.0f}},
        {{0.5f, -0.5f, 0.5f},{1.0f, 0.0f}},
        //back
        {{-0.5f, -0.5f, -0.5f},{1.0f, 0.0f}},
        {{0.5f, -0.5f, -0.5f},{0.0f, 0.0f}},
        {{0.5f, 0.5f, -0.5f},{0.0f, 1.0f}},
        {{-0.5f, 0.5f, -0.5f},{1.0f, 1.0f}},

        //left
        {{-0.5f, -0.5f, -0.5f},{1.0f, 0.0f}},
        {{-0.5f, -0.5f, 0.5f},{0.0f, 0.0f}},
        {{-0.5f, 0.5f, 0.5f},{0.0f, 1.0f}},
        {{-0.5f, 0.5f, -0.5f},{1.0f, 1.0f}},

        //upper
        {{0.5f, 0.5f, 0.5f},{1.0f, 0.0f}},
        {{-0.5f, 0.5f, 0.5f},{0.0f, 0.0f}},
        {{-0.5f, 0.5f, -0.5f},{0.0f, 1.0f}},
        {{0.5f, 0.5f, -0.5f},{1.0f, 1.0f}},

        //bottom
        {{-0.5f, -0.5f, -0.5f},{1.0f, 0.0f}},
        {{0.5f, -0.5f, -0.5f},{0.0f, 0.0f}},
        {{0.5f, -0.5f, 0.5f},{0.0f, 1.0f}},
        {{-0.5f, -0.5f, 0.5f},{1.0f, 1.0f}},
    }};

    mesh.SetMeshData(vertices, {
                         0, 1, 2, 0, 2, 3,
                         4, 5, 6, 4, 6, 7,
                         8, 9, 10, 8, 10, 11,
                         12, 13, 14, 12, 14, 15,
                         16, 17, 18, 16, 18, 19,
                         20, 21, 22, 20, 22, 23});
}

void Primitives::Quad(Mesh& mesh)
{
    std::vector<Vertex> vertices{{
        {{-0.5f , -0.5f , 0.0f},{1.0f , 0.0f}} ,
        {{0.5f , -0.5f , 0.0f},{0.0f , 0.0f}} ,
        {{0.5f , 0.5f , 0.0f},{0.0f , 1.0f}},
        {{-0.5f , 0.5f , 0.0f},{1.0f , 1.0f}},
    }};

    mesh.SetMeshData(vertices, {0, 1, 2, 2, 3, 0});
}

void Primitives::Sphere(Mesh& mesh, float radius, uint32_t rings, uint32_t sectors)
{
    if(radius < 0)
    {
        LOG_WARNING("Sphere radius less then 0! UV will be inverted!");
    }
    if(rings < 4 || sectors < 4)
    {
        LOG_WARNING("Rings or sectors are less then 4, sphere will not be generated!");
        return;
    }

    std::vector<uint32_t> indices;
    std::vector<Vertex> temp_vertices;

    uint32_t vectorSize = rings * sectors;

    if(vectorSize > temp_vertices.max_size())
    {
        LOG_WARNING("Number of vertices is too big, sphere will not be generated!");
        return;
    }

    temp_vertices.resize(rings * sectors);
    {
        float const R = 1. / static_cast<float>(rings - 1);
        float const S = 1. / static_cast<float>(sectors - 1);

        auto vert_iter = temp_vertices.begin();
        for(uint32_t r = 0; r < rings; r++)
        {
            for(uint32_t s = 0; s < sectors; s++)
            {
                float const y = sin(-glm::half_pi<float>() + glm::pi<float>() * r * R);
                float const x = cos(2 * glm::pi<float>() * s * S) * sin(glm::pi<float>() * r * R);
                float const z = sin(2 * glm::pi<float>() * s * S) * sin(glm::pi<float>() * r * R);
                *vert_iter++ = {{x * radius , y * radius , z * radius},{s * S, r * R}};
            }
        }
    }

    indices.resize(sectors * rings * 6);
    auto indices_iter = indices.begin();
    for(uint32_t x = 0; x < sectors; x++)
    {
        for(uint32_t y = 0; y < rings; y++)
        {
            int left = x;
            float right = (x + 1) % sectors;
            float top = y;
            float bottom = (y + 1) % rings;
            *indices_iter++ = {static_cast<uint32_t>(left + top * sectors)};
            *indices_iter++ = {static_cast<uint32_t>(left + bottom * sectors)};
            *indices_iter++ = {static_cast<uint32_t>(right + top * sectors)};
            *indices_iter++ = {static_cast<uint32_t>(right + top * sectors)};
            *indices_iter++ = {static_cast<uint32_t>(left + bottom * sectors)};
            *indices_iter++ = {static_cast<uint32_t>(right + bottom * sectors)};
        }
    }

    mesh.SetMeshData(temp_vertices, indices);
}
}
}
<commit_msg>[#84] Fixed cube rendering<commit_after>/*
* Copyright (C) 2017 by Godlike
* This code is licensed under the MIT license (MIT)
* (http://opensource.org/licenses/MIT)
*/

#include <unicorn/video/Primitives.hpp>
#include <unicorn/utility/Logger.hpp>

#include <glm/gtc/constants.hpp>

namespace unicorn
{
namespace video
{
void Primitives::Cube(Mesh& mesh)
{
    std::vector<Vertex> vertices{{
        //front
        {{-0.5f, -0.5f, 0.5f},{1.0f, 0.0f}},
        {{0.5f, -0.5f, 0.5f},{0.0f, 0.0f}},
        {{0.5f, 0.5f, 0.5f},{0.0f, 1.0f}},
        {{-0.5f, 0.5f, 0.5f},{1.0f, 1.0f}},

        //right
        {{0.5f, 0.5f, 0.5f},{1.0f, 1.0f}},
        {{0.5f, 0.5f, -0.5f},{0.0f, 1.0f}},
        {{0.5f, -0.5f, -0.5f},{0.0f, 0.0f}},
        {{0.5f, -0.5f, 0.5f},{1.0f, 0.0f}},

        //back
        {{-0.5f, -0.5f, -0.5f},{1.0f, 0.0f}},
        {{0.5f, -0.5f, -0.5f},{0.0f, 0.0f}},
        {{0.5f, 0.5f, -0.5f},{0.0f, 1.0f}},
        {{-0.5f, 0.5f, -0.5f},{1.0f, 1.0f}},

        //left
        {{-0.5f, -0.5f, -0.5f},{1.0f, 0.0f}},
        {{-0.5f, -0.5f, 0.5f},{0.0f, 0.0f}},
        {{-0.5f, 0.5f, 0.5f},{0.0f, 1.0f}},
        {{-0.5f, 0.5f, -0.5f},{1.0f, 1.0f}},

        //upper
        {{0.5f, 0.5f, 0.5f},{1.0f, 0.0f}},
        {{-0.5f, 0.5f, 0.5f},{0.0f, 0.0f}},
        {{-0.5f, 0.5f, -0.5f},{0.0f, 1.0f}},
        {{0.5f, 0.5f, -0.5f},{1.0f, 1.0f}},

        //bottom
        {{-0.5f, -0.5f, -0.5f},{1.0f, 0.0f}},
        {{0.5f, -0.5f, -0.5f},{0.0f, 0.0f}},
        {{0.5f, -0.5f, 0.5f},{0.0f, 1.0f}},
        {{-0.5f, -0.5f, 0.5f},{1.0f, 1.0f}},
    }};

    mesh.SetMeshData(vertices, {
                         0, 1, 2, 0, 2, 3,
                         4, 5, 6, 4, 6, 7,
                         8, 9, 10, 8, 10, 11,
                         12, 13, 14, 12, 14, 15,
                         16, 17, 18, 16, 18, 19,
                         20, 21, 22, 20, 22, 23});
}

void Primitives::Quad(Mesh& mesh)
{
    std::vector<Vertex> vertices{{
        {{-0.5f , -0.5f , 0.0f},{1.0f , 0.0f}} ,
        {{0.5f , -0.5f , 0.0f},{0.0f , 0.0f}} ,
        {{0.5f , 0.5f , 0.0f},{0.0f , 1.0f}},
        {{-0.5f , 0.5f , 0.0f},{1.0f , 1.0f}},
    }};

    mesh.SetMeshData(vertices, {0, 1, 2, 2, 3, 0});
}

void Primitives::Sphere(Mesh& mesh, float radius, uint32_t rings, uint32_t sectors)
{
    if(radius < 0)
    {
        LOG_WARNING("Sphere radius less then 0! UV will be inverted!");
    }
    if(rings < 4 || sectors < 4)
    {
        LOG_WARNING("Rings or sectors are less then 4, sphere will not be generated!");
        return;
    }

    std::vector<uint32_t> indices;
    std::vector<Vertex> temp_vertices;

    uint32_t vectorSize = rings * sectors;

    if(vectorSize > temp_vertices.max_size())
    {
        LOG_WARNING("Number of vertices is too big, sphere will not be generated!");
        return;
    }

    temp_vertices.resize(rings * sectors);
    {
        float const R = 1.f / static_cast<float>(rings - 1);
        float const S = 1.f / static_cast<float>(sectors - 1);

        auto vert_iter = temp_vertices.begin();
        for(uint32_t r = 0; r < rings; r++)
        {
            for(uint32_t s = 0; s < sectors; s++)
            {
                float const y = sin(-glm::half_pi<float>() + glm::pi<float>() * r * R);
                float const x = cos(2 * glm::pi<float>() * s * S) * sin(glm::pi<float>() * r * R);
                float const z = sin(2 * glm::pi<float>() * s * S) * sin(glm::pi<float>() * r * R);
                *vert_iter++ = {{x * radius , y * radius , z * radius},{s * S, r * R}};
            }
        }
    }

    indices.resize(sectors * rings * 6);
    auto indices_iter = indices.begin();
    for(uint32_t x = 0; x < sectors; x++)
    {
        for(uint32_t y = 0; y < rings; y++)
        {
            uint32_t left = x;
            float right = static_cast<float>((x + 1) % sectors);
            float top = static_cast<float>(y);
            float bottom = static_cast<float>((y + 1) % rings);
            *indices_iter++ = {static_cast<uint32_t>(left + top * sectors)};
            *indices_iter++ = {static_cast<uint32_t>(left + bottom * sectors)};
            *indices_iter++ = {static_cast<uint32_t>(right + top * sectors)};
            *indices_iter++ = {static_cast<uint32_t>(right + top * sectors)};
            *indices_iter++ = {static_cast<uint32_t>(left + bottom * sectors)};
            *indices_iter++ = {static_cast<uint32_t>(right + bottom * sectors)};
        }
    }

    mesh.SetMeshData(temp_vertices, indices);
}
}
}
<|endoftext|>