<commit_before>//=============================================================================================================
/**
* @file     realtimemultisamplearraydelegate.cpp
* @author   Christoph Dinh <chdinh@nmr.mgh.harvard.edu>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     May, 2014
*
* @section  LICENSE
*
* Copyright (C) 2014, Christoph Dinh and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions 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.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may 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 COPYRIGHT OWNER 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.
*
*
* @brief    Implementation of the RealTimeMultiSampleArrayDelegate Class.
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "realtimemultisamplearraydelegate.h"

#include "realtimemultisamplearraymodel.h"

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QPainter>
#include <QPainterPath>
#include <QDebug>
#include <QThread>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace XDISPLIB;

//*************************************************************************************************************
//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

RealTimeMultiSampleArrayDelegate::RealTimeMultiSampleArrayDelegate(QObject *parent)
: QAbstractItemDelegate(parent)
{

}

//*************************************************************************************************************

void RealTimeMultiSampleArrayDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    float t_fPlotHeight = option.rect.height();
    switch(index.column()) {
        case 0: { //chnames
            painter->save();

            painter->rotate(-90);
            painter->drawText(QRectF(-option.rect.y()-t_fPlotHeight,0,t_fPlotHeight,20),Qt::AlignCenter,index.model()->data(index,Qt::DisplayRole).toString());

            painter->restore();
            break;
        }
        case 1: { //data plot
            painter->save();

            //draw special background when channel is marked as bad
//            QVariant v = index.model()->data(index,Qt::BackgroundRole);
//            if(v.canConvert<QBrush>() && !(option.state & QStyle::State_Selected)) {
//                QPointF oldBO = painter->brushOrigin();
//                painter->setBrushOrigin(option.rect.topLeft());
//                painter->fillRect(option.rect, qvariant_cast<QBrush>(v));
//                painter->setBrushOrigin(oldBO);
//            }

//            //Highlight selected channels
//            if(option.state & QStyle::State_Selected) {
//                QPointF oldBO = painter->brushOrigin();
//                painter->setBrushOrigin(option.rect.topLeft());
//                painter->fillRect(option.rect, option.palette.highlight());
//                painter->setBrushOrigin(oldBO);
//            }

            //Get data
            QVariant variant = index.model()->data(index,Qt::DisplayRole);
            QList< QVector<float> > data = variant.value< QList< QVector<float> > >();

            const RealTimeMultiSampleArrayModel* t_pModel = static_cast<const RealTimeMultiSampleArrayModel*>(index.model());

            if(data.size() > 0)
            {
    //            const RealTimeMultiSampleArrayModel* t_rtmsaModel = (static_cast<const RealTimeMultiSampleArrayModel*>(index.model()));

                QPainterPath path(QPointF(option.rect.x(),option.rect.y()));//QPointF(option.rect.x()+t_rtmsaModel->relFiffCursor()-1,option.rect.y()));

                //Plot grid
                painter->setRenderHint(QPainter::Antialiasing, false);
                createGridPath(index, option, path, data);

                painter->save();
                QPen pen;
                pen.setStyle(Qt::DotLine);
                pen.setWidthF(0.5);
                painter->setPen(pen);
                painter->drawPath(path);
                painter->restore();

                //Plot data path
                path = QPainterPath(QPointF(option.rect.x(),option.rect.y()));//QPointF(option.rect.x()+t_rtmsaModel->relFiffCursor(),option.rect.y()));
                QPainterPath lastPath(QPointF(option.rect.x(),option.rect.y()));

                createPlotPath(index, option, path, lastPath, data[0], data[1]);

                painter->save();
                painter->translate(0,t_fPlotHeight/2);
                painter->setRenderHint(QPainter::Antialiasing, true);

                if(option.state & QStyle::State_Selected)
                    painter->setPen(QPen(t_pModel->isFreezed() ? Qt::darkRed : Qt::red, 1, Qt::SolidLine));
                else
                    painter->setPen(QPen(t_pModel->isFreezed() ? Qt::darkGray : Qt::darkBlue, 1, Qt::SolidLine));

                painter->drawPath(path);
                painter->restore();

                //Plot last data path
                painter->translate(0,t_fPlotHeight/2);
                painter->setRenderHint(QPainter::Antialiasing, true);
                if(option.state & QStyle::State_Selected)
                    painter->setPen(QPen(t_pModel->isFreezed() ? Qt::darkRed : Qt::red, 1, Qt::SolidLine));
                else
                    painter->setPen(QPen(t_pModel->isFreezed() ? Qt::darkGray : Qt::darkBlue, 1, Qt::SolidLine));
                painter->drawPath(lastPath);

                painter->restore();
            }
            break;
        }
    }

}

//*************************************************************************************************************

QSize RealTimeMultiSampleArrayDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QSize size;

    switch(index.column()) {
    case 0:
        size = QSize(20,option.rect.height());
        break;
    case 1:
        QList< QVector<float> > data = index.model()->data(index).value< QList<QVector<float> > >();
//        qint32 nsamples = (static_cast<const RealTimeMultiSampleArrayModel*>(index.model()))->lastSample()-(static_cast<const RealTimeMultiSampleArrayModel*>(index.model()))->firstSample();

//        size = QSize(nsamples*m_dDx,m_dPlotHeight);
        Q_UNUSED(option);
        break;
    }

    return size;
}

//*************************************************************************************************************

void RealTimeMultiSampleArrayDelegate::createPlotPath(const QModelIndex &index, const QStyleOptionViewItem &option, QPainterPath& path, QPainterPath& lastPath, QVector<float>& data, QVector<float>& lastData) const
{
    const RealTimeMultiSampleArrayModel* t_pModel = static_cast<const RealTimeMultiSampleArrayModel*>(index.model());

    //get maximum range of respective channel type (range value in FiffChInfo does not seem to contain a reasonable value)
    qint32 kind = t_pModel->getKind(index.row());
    float fMaxValue = 1e-9f;

    float Amp = 1e-9f;

    switch(kind) {
        case FIFFV_MEG_CH: {
            qint32 unit =t_pModel->getUnit(index.row());
            if(unit == FIFF_UNIT_T_M) {
                fMaxValue = 1e-10f;
                if(t_pModel->getScaling().contains(FIFF_UNIT_T_M))
                    fMaxValue = t_pModel->getScaling()[FIFF_UNIT_T_M];
            }
            else if(unit == FIFF_UNIT_T)
            {
                if(t_pModel->getCoil(index.row()) == FIFFV_COIL_BABY_MAG)
                    fMaxValue = 1e-11f;
                else
                    fMaxValue = 1e-11f;

                if(t_pModel->getScaling().contains(FIFF_UNIT_T))
                    fMaxValue = t_pModel->getScaling()[FIFF_UNIT_T];
            }
            Amp = 1e-10f;

            break;
        }

        case FIFFV_REF_MEG_CH: {  /*11/04/14 Added by Limin: MEG reference channel */
            fMaxValue = 1e-11f;

            if(t_pModel->getScaling().contains(FIFF_UNIT_T))
                fMaxValue = t_pModel->getScaling()[FIFF_UNIT_T];

            Amp = 1e-10f;

            break;
        }
        case FIFFV_EEG_CH: {
            fMaxValue = 1e-4f;
            if(t_pModel->getScaling().contains(FIFFV_EEG_CH))
                fMaxValue = t_pModel->getScaling()[FIFFV_EEG_CH];
            Amp = 1e-4f;
            break;
        }
        case FIFFV_EOG_CH: {
            fMaxValue = 1e-3f;
            if(t_pModel->getScaling().contains(FIFFV_EOG_CH))
                fMaxValue = t_pModel->getScaling()[FIFFV_EOG_CH];
            Amp = 1e-3f;
            break;
        }
        case FIFFV_STIM_CH: {
            fMaxValue = 5;
            if(t_pModel->getScaling().contains(FIFFV_STIM_CH))
                fMaxValue = t_pModel->getScaling()[FIFFV_STIM_CH];
            Amp = 1.0f;
            break;
        }
        case FIFFV_MISC_CH: {
            fMaxValue = 1e-3f;
            if(t_pModel->getScaling().contains(FIFFV_MISC_CH))
                fMaxValue = t_pModel->getScaling()[FIFFV_MISC_CH];
            Amp = 1e-3f;
            break;
        }
    }

    float fValue;
    //float fScaleY = option.rect.height()/(2*fMaxValue);
    float fScaleY = Amp / fMaxValue;

    float y_base = path.currentPosition().y();
    QPointF qSamplePosition;

    float fDx = ((float)option.rect.width()) / t_pModel->getMaxSamples();

    //Move to initial starting point
    if(data.size() > 0)
    {
//        float val = data[0];
        fValue = 0;//(val-data[0])*fScaleY;

        float newY = y_base-fValue;//Reverse direction -> plot the right way

        qSamplePosition.setY(newY);
        qSamplePosition.setX(path.currentPosition().x());

        path.moveTo(qSamplePosition);
    }

    //create lines from one to the next sample
    qint32 i;
    for(i = 1; i < data.size(); ++i) {
        float val = data[i] - data[0]; //remove first sample data[0] as offset
        fValue = val*fScaleY;
        //qDebug()<<"val"<<val<<"fScaleY"<<fScaleY<<"fValue"<<fValue;

        float newY = y_base-fValue;//Reverse direction -> plot the right way

        qSamplePosition.setY(newY);
        qSamplePosition.setX(path.currentPosition().x()+fDx);

        path.lineTo(qSamplePosition);
    }

    //create lines from one to the next sample for last path
    qint32 sample_offset = t_pModel->numVLines() + 1;
    qSamplePosition.setX(qSamplePosition.x() + fDx*sample_offset);
    lastPath.moveTo(qSamplePosition);

    for(i += sample_offset; i < lastData.size(); ++i) {
        float val = lastData[i] - lastData[0]; //remove first sample lastData[0] as offset
        fValue = val*fScaleY;

        float newY = y_base-fValue;

        qSamplePosition.setY(newY);
        qSamplePosition.setX(lastPath.currentPosition().x()+fDx);

        lastPath.lineTo(qSamplePosition);
    }
}

//*************************************************************************************************************

void RealTimeMultiSampleArrayDelegate::createGridPath(const QModelIndex &index, const QStyleOptionViewItem &option, QPainterPath& path, QList< QVector<float> >& data) const
{
    Q_UNUSED(data)

    const RealTimeMultiSampleArrayModel* t_pModel = static_cast<const RealTimeMultiSampleArrayModel*>(index.model());

    if(t_pModel->numVLines() > 0)
    {
        //horizontal lines
        float distance = option.rect.width()/(t_pModel->numVLines()+1);

        float yStart = option.rect.topLeft().y();

        float yEnd = option.rect.bottomRight().y();

        for(qint8 i = 0; i < t_pModel->numVLines(); ++i) {
            float x = distance*(i+1);
            path.moveTo(x,yStart);
            path.lineTo(x,yEnd);
        }
    }
}
<commit_msg>corrected scaling<commit_after>//=============================================================================================================
/**
* @file     realtimemultisamplearraydelegate.cpp
* @author   Christoph Dinh <chdinh@nmr.mgh.harvard.edu>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     May, 2014
*
* @section  LICENSE
*
* Copyright (C) 2014, Christoph Dinh and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions 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.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may 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 COPYRIGHT OWNER 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.
*
*
* @brief    Implementation of the RealTimeMultiSampleArrayDelegate Class.
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "realtimemultisamplearraydelegate.h"

#include "realtimemultisamplearraymodel.h"

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QPainter>
#include <QPainterPath>
#include <QDebug>
#include <QThread>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace XDISPLIB;

//*************************************************************************************************************
//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

RealTimeMultiSampleArrayDelegate::RealTimeMultiSampleArrayDelegate(QObject *parent)
: QAbstractItemDelegate(parent)
{

}

//*************************************************************************************************************

void RealTimeMultiSampleArrayDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    float t_fPlotHeight = option.rect.height();
    switch(index.column()) {
        case 0: { //chnames
            painter->save();

            painter->rotate(-90);
            painter->drawText(QRectF(-option.rect.y()-t_fPlotHeight,0,t_fPlotHeight,20),Qt::AlignCenter,index.model()->data(index,Qt::DisplayRole).toString());

            painter->restore();
            break;
        }
        case 1: { //data plot
            painter->save();

            //draw special background when channel is marked as bad
//            QVariant v = index.model()->data(index,Qt::BackgroundRole);
//            if(v.canConvert<QBrush>() && !(option.state & QStyle::State_Selected)) {
//                QPointF oldBO = painter->brushOrigin();
//                painter->setBrushOrigin(option.rect.topLeft());
//                painter->fillRect(option.rect, qvariant_cast<QBrush>(v));
//                painter->setBrushOrigin(oldBO);
//            }

//            //Highlight selected channels
//            if(option.state & QStyle::State_Selected) {
//                QPointF oldBO = painter->brushOrigin();
//                painter->setBrushOrigin(option.rect.topLeft());
//                painter->fillRect(option.rect, option.palette.highlight());
//                painter->setBrushOrigin(oldBO);
//            }

            //Get data
            QVariant variant = index.model()->data(index,Qt::DisplayRole);
            QList< QVector<float> > data = variant.value< QList< QVector<float> > >();

            const RealTimeMultiSampleArrayModel* t_pModel = static_cast<const RealTimeMultiSampleArrayModel*>(index.model());

            if(data.size() > 0)
            {
    //            const RealTimeMultiSampleArrayModel* t_rtmsaModel = (static_cast<const RealTimeMultiSampleArrayModel*>(index.model()));

                QPainterPath path(QPointF(option.rect.x(),option.rect.y()));//QPointF(option.rect.x()+t_rtmsaModel->relFiffCursor()-1,option.rect.y()));

                //Plot grid
                painter->setRenderHint(QPainter::Antialiasing, false);
                createGridPath(index, option, path, data);

                painter->save();
                QPen pen;
                pen.setStyle(Qt::DotLine);
                pen.setWidthF(0.5);
                painter->setPen(pen);
                painter->drawPath(path);
                painter->restore();

                //Plot data path
                path = QPainterPath(QPointF(option.rect.x(),option.rect.y()));//QPointF(option.rect.x()+t_rtmsaModel->relFiffCursor(),option.rect.y()));
                QPainterPath lastPath(QPointF(option.rect.x(),option.rect.y()));

                createPlotPath(index, option, path, lastPath, data[0], data[1]);

                painter->save();
                painter->translate(0,t_fPlotHeight/2);
                painter->setRenderHint(QPainter::Antialiasing, true);

                if(option.state & QStyle::State_Selected)
                    painter->setPen(QPen(t_pModel->isFreezed() ? Qt::darkRed : Qt::red, 1, Qt::SolidLine));
                else
                    painter->setPen(QPen(t_pModel->isFreezed() ? Qt::darkGray : Qt::darkBlue, 1, Qt::SolidLine));

                painter->drawPath(path);
                painter->restore();

                //Plot last data path
                painter->translate(0,t_fPlotHeight/2);
                painter->setRenderHint(QPainter::Antialiasing, true);
                if(option.state & QStyle::State_Selected)
                    painter->setPen(QPen(t_pModel->isFreezed() ? Qt::darkRed : Qt::red, 1, Qt::SolidLine));
                else
                    painter->setPen(QPen(t_pModel->isFreezed() ? Qt::darkGray : Qt::darkBlue, 1, Qt::SolidLine));
                painter->drawPath(lastPath);

                painter->restore();
            }
            break;
        }
    }

}

//*************************************************************************************************************

QSize RealTimeMultiSampleArrayDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QSize size;

    switch(index.column()) {
    case 0:
        size = QSize(20,option.rect.height());
        break;
    case 1:
        QList< QVector<float> > data = index.model()->data(index).value< QList<QVector<float> > >();
//        qint32 nsamples = (static_cast<const RealTimeMultiSampleArrayModel*>(index.model()))->lastSample()-(static_cast<const RealTimeMultiSampleArrayModel*>(index.model()))->firstSample();

//        size = QSize(nsamples*m_dDx,m_dPlotHeight);
        Q_UNUSED(option);
        break;
    }

    return size;
}

//*************************************************************************************************************

void RealTimeMultiSampleArrayDelegate::createPlotPath(const QModelIndex &index, const QStyleOptionViewItem &option, QPainterPath& path, QPainterPath& lastPath, QVector<float>& data, QVector<float>& lastData) const
{
    const RealTimeMultiSampleArrayModel* t_pModel = static_cast<const RealTimeMultiSampleArrayModel*>(index.model());

    //get maximum range of respective channel type (range value in FiffChInfo does not seem to contain a reasonable value)
    qint32 kind = t_pModel->getKind(index.row());
    float fMaxValue = 1e-9f;
//    float Amp = 1e-9f;

    switch(kind) {
        case FIFFV_MEG_CH: {
            qint32 unit =t_pModel->getUnit(index.row());
            if(unit == FIFF_UNIT_T_M) {
                fMaxValue = 1e-10f;
                if(t_pModel->getScaling().contains(FIFF_UNIT_T_M))
                    fMaxValue = t_pModel->getScaling()[FIFF_UNIT_T_M];
            }
            else if(unit == FIFF_UNIT_T)
            {
                if(t_pModel->getCoil(index.row()) == FIFFV_COIL_BABY_MAG)
                    fMaxValue = 1e-11f;
                else
                    fMaxValue = 1e-11f;

                if(t_pModel->getScaling().contains(FIFF_UNIT_T))
                    fMaxValue = t_pModel->getScaling()[FIFF_UNIT_T];
            }
//            Amp = 1e-10f;
            break;
        }

        case FIFFV_REF_MEG_CH: {  /*11/04/14 Added by Limin: MEG reference channel */
            fMaxValue = 1e-11f;

            if(t_pModel->getScaling().contains(FIFF_UNIT_T))
                fMaxValue = t_pModel->getScaling()[FIFF_UNIT_T];
//            Amp = 1e-10f;
            break;
        }
        case FIFFV_EEG_CH: {
            fMaxValue = 1e-4f;
            if(t_pModel->getScaling().contains(FIFFV_EEG_CH))
                fMaxValue = t_pModel->getScaling()[FIFFV_EEG_CH];
//            Amp = 1e-4f;
            break;
        }
        case FIFFV_EOG_CH: {
            fMaxValue = 1e-3f;
            if(t_pModel->getScaling().contains(FIFFV_EOG_CH))
                fMaxValue = t_pModel->getScaling()[FIFFV_EOG_CH];
//            Amp = 1e-3f;
            break;
        }
        case FIFFV_STIM_CH: {
            fMaxValue = 5;
            if(t_pModel->getScaling().contains(FIFFV_STIM_CH))
                fMaxValue = t_pModel->getScaling()[FIFFV_STIM_CH];
//            Amp = 1.0f;
            break;
        }
        case FIFFV_MISC_CH: {
            fMaxValue = 1e-3f;
            if(t_pModel->getScaling().contains(FIFFV_MISC_CH))
                fMaxValue = t_pModel->getScaling()[FIFFV_MISC_CH];
//            Amp = 1e-3f;
            break;
        }
    }

    float fValue;
    float fScaleY = option.rect.height()/(2*fMaxValue);
//    float fScaleY = Amp / fMaxValue;

    float y_base = path.currentPosition().y();
    QPointF qSamplePosition;

    float fDx = ((float)option.rect.width()) / t_pModel->getMaxSamples();

    //Move to initial starting point
    if(data.size() > 0)
    {
//        float val = data[0];
        fValue = 0;//(val-data[0])*fScaleY;

        float newY = y_base-fValue;//Reverse direction -> plot the right way

        qSamplePosition.setY(newY);
        qSamplePosition.setX(path.currentPosition().x());

        path.moveTo(qSamplePosition);
    }

    //create lines from one to the next sample
    qint32 i;
    for(i = 1; i < data.size(); ++i) {
        float val = data[i] - data[0]; //remove first sample data[0] as offset
        fValue = val*fScaleY;
        //qDebug()<<"val"<<val<<"fScaleY"<<fScaleY<<"fValue"<<fValue;

        float newY = y_base-fValue;//Reverse direction -> plot the right way

        qSamplePosition.setY(newY);
        qSamplePosition.setX(path.currentPosition().x()+fDx);

        path.lineTo(qSamplePosition);
    }

    //create lines from one to the next sample for last path
    qint32 sample_offset = t_pModel->numVLines() + 1;
    qSamplePosition.setX(qSamplePosition.x() + fDx*sample_offset);
    lastPath.moveTo(qSamplePosition);

    for(i += sample_offset; i < lastData.size(); ++i) {
        float val = lastData[i] - lastData[0]; //remove first sample lastData[0] as offset
        fValue = val*fScaleY;

        float newY = y_base-fValue;

        qSamplePosition.setY(newY);
        qSamplePosition.setX(lastPath.currentPosition().x()+fDx);

        lastPath.lineTo(qSamplePosition);
    }
}

//*************************************************************************************************************

void RealTimeMultiSampleArrayDelegate::createGridPath(const QModelIndex &index, const QStyleOptionViewItem &option, QPainterPath& path, QList< QVector<float> >& data) const
{
    Q_UNUSED(data)

    const RealTimeMultiSampleArrayModel* t_pModel = static_cast<const RealTimeMultiSampleArrayModel*>(index.model());

    if(t_pModel->numVLines() > 0)
    {
        //horizontal lines
        float distance = option.rect.width()/(t_pModel->numVLines()+1);

        float yStart = option.rect.topLeft().y();

        float yEnd = option.rect.bottomRight().y();

        for(qint8 i = 0; i < t_pModel->numVLines(); ++i) {
            float x = distance*(i+1);
            path.moveTo(x,yStart);
            path.lineTo(x,yEnd);
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
// This file was copied from apache::thrift::server::TThreadedServer.cpp v0.9.0, with the
// significant changes noted inline below.

#include "rpc/TAcceptQueueServer.h"

#include <thrift/concurrency/PlatformThreadFactory.h>

#include "util/thread-pool.h"

DEFINE_int32(accepted_cnxn_queue_depth, 10000,
    "(Advanced) The size of the post-accept, pre-setup connection queue for Impala "
    "internal connections");

namespace apache {
namespace thrift {
namespace server {

using boost::shared_ptr;
using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::thrift::concurrency;
using namespace impala;

class TAcceptQueueServer::Task : public Runnable {
 public:
  Task(TAcceptQueueServer& server, shared_ptr<TProcessor> processor,
      shared_ptr<TProtocol> input, shared_ptr<TProtocol> output,
      shared_ptr<TTransport> transport)
    : server_(server),
      processor_(std::move(processor)),
      input_(std::move(input)),
      output_(std::move(output)),
      transport_(std::move(transport)) {}

  ~Task() override = default;

  void run() override {
    boost::shared_ptr<TServerEventHandler> eventHandler = server_.getEventHandler();
    void* connectionContext = nullptr;
    if (eventHandler != nullptr) {
      connectionContext = eventHandler->createContext(input_, output_);
    }
    try {
      for (;;) {
        if (eventHandler != nullptr) {
          eventHandler->processContext(connectionContext, transport_);
        }
        if (!processor_->process(input_, output_, connectionContext)
            || !input_->getTransport()->peek()) {
          break;
        }
      }
    } catch (const TTransportException& ttx) {
      if (ttx.getType() != TTransportException::END_OF_FILE) {
        string errStr = string("TAcceptQueueServer client died: ") + ttx.what();
        GlobalOutput(errStr.c_str());
      }
    } catch (const std::exception& x) {
      GlobalOutput.printf(
          "TAcceptQueueServer exception: %s: %s", typeid(x).name(), x.what());
    } catch (...) {
      GlobalOutput("TAcceptQueueServer uncaught exception.");
    }
    if (eventHandler != nullptr) {
      eventHandler->deleteContext(connectionContext, input_, output_);
    }

    try {
      input_->getTransport()->close();
    } catch (TTransportException& ttx) {
      string errStr = string("TAcceptQueueServer input close failed: ") + ttx.what();
      GlobalOutput(errStr.c_str());
    }
    try {
      output_->getTransport()->close();
    } catch (TTransportException& ttx) {
      string errStr = string("TAcceptQueueServer output close failed: ") + ttx.what();
      GlobalOutput(errStr.c_str());
    }

    // Remove this task from parent bookkeeping
    {
      Synchronized s(server_.tasksMonitor_);
      server_.tasks_.erase(this);
      server_.tasksMonitor_.notify();
    }
  }

 private:
  TAcceptQueueServer& server_;
  friend class TAcceptQueueServer;

  shared_ptr<TProcessor> processor_;
  shared_ptr<TProtocol> input_;
  shared_ptr<TProtocol> output_;
  shared_ptr<TTransport> transport_;
};

TAcceptQueueServer::TAcceptQueueServer(const boost::shared_ptr<TProcessor>& processor,
    const boost::shared_ptr<TServerTransport>& serverTransport,
    const boost::shared_ptr<TTransportFactory>& transportFactory,
    const boost::shared_ptr<TProtocolFactory>& protocolFactory,
    const boost::shared_ptr<ThreadFactory>& threadFactory,
    int32_t maxTasks)
    : TServer(processor, serverTransport, transportFactory, protocolFactory),
      threadFactory_(threadFactory), maxTasks_(maxTasks) {
  init();
}

void TAcceptQueueServer::init() {
  stop_ = false;
  metrics_enabled_ = false;
  queue_size_metric_ = nullptr;

  if (!threadFactory_) {
    threadFactory_.reset(new PlatformThreadFactory);
  }
}

// New.
void TAcceptQueueServer::SetupConnection(boost::shared_ptr<TTransport> client) {
  if (metrics_enabled_) queue_size_metric_->Increment(-1);
  shared_ptr<TTransport> inputTransport;
  shared_ptr<TTransport> outputTransport;
  try {
    inputTransport = inputTransportFactory_->getTransport(client);
    outputTransport = outputTransportFactory_->getTransport(client);
    shared_ptr<TProtocol> inputProtocol =
        inputProtocolFactory_->getProtocol(inputTransport);
    shared_ptr<TProtocol> outputProtocol =
        outputProtocolFactory_->getProtocol(outputTransport);

    shared_ptr<TProcessor> processor =
        getProcessor(inputProtocol, outputProtocol, client);

    TAcceptQueueServer::Task* task = new TAcceptQueueServer::Task(
        *this, processor, inputProtocol, outputProtocol, client);

    // Create a task
    shared_ptr<Runnable> runnable = shared_ptr<Runnable>(task);

    // Create a thread for this task
    shared_ptr<Thread> thread = shared_ptr<Thread>(threadFactory_->newThread(runnable));

    // Insert thread into the set of threads
    {
      Synchronized s(tasksMonitor_);
      while (maxTasks_ > 0 && tasks_.size() >= maxTasks_) {
        tasksMonitor_.wait();
      }
      tasks_.insert(task);
    }

    // Start the thread!
    thread->start();
  } catch (TException& tx) {
    if (inputTransport != nullptr) {
      inputTransport->close();
    }
    if (outputTransport != nullptr) {
      outputTransport->close();
    }
    if (client != nullptr) {
      client->close();
    }
    string errStr = string("TAcceptQueueServer: Caught TException: ") + tx.what();
    GlobalOutput(errStr.c_str());
  } catch (string s) {
    if (inputTransport != nullptr) {
      inputTransport->close();
    }
    if (outputTransport != nullptr) {
      outputTransport->close();
    }
    if (client != nullptr) {
      client->close();
    }
    string errStr = "TAcceptQueueServer: Unknown exception: " + s;
    GlobalOutput(errStr.c_str());
  }
}

void TAcceptQueueServer::serve() {
  // Start the server listening
  serverTransport_->listen();

  // Run the preServe event
  if (eventHandler_ != nullptr) {
    eventHandler_->preServe();
  }

  // Only using one thread here is sufficient for performance, and it avoids potential
  // thread safety issues with the thrift code called in SetupConnection.
  constexpr int CONNECTION_SETUP_POOL_SIZE = 1;

  // New - this is the thread pool used to process the internal accept queue.
  ThreadPool<shared_ptr<TTransport>> connection_setup_pool("setup-server", "setup-worker",
      CONNECTION_SETUP_POOL_SIZE, FLAGS_accepted_cnxn_queue_depth,
      [this](int tid, const shared_ptr<TTransport>& item) {
        this->SetupConnection(item);
      });
  // Initialize the thread pool
  Status status = connection_setup_pool.Init();
  if (!status.ok()) {
    status.AddDetail("TAcceptQueueServer: thread pool could not start.");
    string errStr = status.GetDetail();
    GlobalOutput(errStr.c_str());
    stop_ = true;
  }

  while (!stop_) {
    try {
      // Fetch client from server
      shared_ptr<TTransport> client = serverTransport_->accept();

      // New - the work done to setup the connection has been moved to SetupConnection.
      if (!connection_setup_pool.Offer(std::move(client))) {
        string errStr = string("TAcceptQueueServer: thread pool unexpectedly shut down.");
        GlobalOutput(errStr.c_str());
        stop_ = true;
        break;
      }
      if (metrics_enabled_) queue_size_metric_->Increment(1);
    } catch (TTransportException& ttx) {
      if (!stop_ || ttx.getType() != TTransportException::INTERRUPTED) {
        string errStr =
            string("TAcceptQueueServer: TServerTransport died on accept: ") + ttx.what();
        GlobalOutput(errStr.c_str());
      }
      continue;
    } catch (TException& tx) {
      string errStr = string("TAcceptQueueServer: Caught TException: ") + tx.what();
      GlobalOutput(errStr.c_str());
      continue;
    } catch (string s) {
      string errStr = "TAcceptQueueServer: Unknown exception: " + s;
      GlobalOutput(errStr.c_str());
      break;
    }
  }

  // If stopped manually, make sure to close server transport
  if (stop_) {
    try {
      serverTransport_->close();
      connection_setup_pool.Shutdown();
    } catch (TException& tx) {
      string errStr = string("TAcceptQueueServer: Exception shutting down: ") + tx.what();
      GlobalOutput(errStr.c_str());
    }
    try {
      Synchronized s(tasksMonitor_);
      while (!tasks_.empty()) {
        tasksMonitor_.wait();
      }
    } catch (TException& tx) {
      string errStr =
          string("TAcceptQueueServer: Exception joining workers: ") + tx.what();
      GlobalOutput(errStr.c_str());
    }
    stop_ = false;
  }
}

void TAcceptQueueServer::InitMetrics(MetricGroup* metrics, const string& key_prefix) {
  DCHECK(metrics != nullptr);
  stringstream queue_size_ss;
  queue_size_ss << key_prefix << ".connection-setup-queue-size";
  queue_size_metric_ = metrics->AddGauge(queue_size_ss.str(), 0);
  metrics_enabled_ = true;
}

} // namespace server
} // namespace thrift
} // namespace apache
<commit_msg>IMPALA-7565: Add startup flag to set thrift connection setup thread pool size<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
// This file was copied from apache::thrift::server::TThreadedServer.cpp v0.9.0, with the
// significant changes noted inline below.

#include "rpc/TAcceptQueueServer.h"

#include <thrift/concurrency/PlatformThreadFactory.h>

#include "util/thread-pool.h"

DEFINE_int32(accepted_cnxn_queue_depth, 10000,
    "(Advanced) The size of the post-accept, pre-setup connection queue in each thrift "
    "server set up to service Impala internal and external connections.");

DEFINE_int32_hidden(accepted_cnxn_setup_thread_pool_size, 1,
    "(Advanced) The size of the thread pool that is used to process the "
    "post-accept, pre-setup connection queue in each thrift server set up to service "
    "Impala internal and external connections. Warning: This is untested for values "
    "greater than 1 which might exhibit unpredictable behavior and/or cause crashes.");

namespace apache {
namespace thrift {
namespace server {

using boost::shared_ptr;
using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::thrift::concurrency;
using namespace impala;

class TAcceptQueueServer::Task : public Runnable {
 public:
  Task(TAcceptQueueServer& server, shared_ptr<TProcessor> processor,
      shared_ptr<TProtocol> input, shared_ptr<TProtocol> output,
      shared_ptr<TTransport> transport)
    : server_(server),
      processor_(std::move(processor)),
      input_(std::move(input)),
      output_(std::move(output)),
      transport_(std::move(transport)) {}

  ~Task() override = default;

  void run() override {
    boost::shared_ptr<TServerEventHandler> eventHandler = server_.getEventHandler();
    void* connectionContext = nullptr;
    if (eventHandler != nullptr) {
      connectionContext = eventHandler->createContext(input_, output_);
    }
    try {
      for (;;) {
        if (eventHandler != nullptr) {
          eventHandler->processContext(connectionContext, transport_);
        }
        if (!processor_->process(input_, output_, connectionContext)
            || !input_->getTransport()->peek()) {
          break;
        }
      }
    } catch (const TTransportException& ttx) {
      if (ttx.getType() != TTransportException::END_OF_FILE) {
        string errStr = string("TAcceptQueueServer client died: ") + ttx.what();
        GlobalOutput(errStr.c_str());
      }
    } catch (const std::exception& x) {
      GlobalOutput.printf(
          "TAcceptQueueServer exception: %s: %s", typeid(x).name(), x.what());
    } catch (...) {
      GlobalOutput("TAcceptQueueServer uncaught exception.");
    }
    if (eventHandler != nullptr) {
      eventHandler->deleteContext(connectionContext, input_, output_);
    }

    try {
      input_->getTransport()->close();
    } catch (TTransportException& ttx) {
      string errStr = string("TAcceptQueueServer input close failed: ") + ttx.what();
      GlobalOutput(errStr.c_str());
    }
    try {
      output_->getTransport()->close();
    } catch (TTransportException& ttx) {
      string errStr = string("TAcceptQueueServer output close failed: ") + ttx.what();
      GlobalOutput(errStr.c_str());
    }

    // Remove this task from parent bookkeeping
    {
      Synchronized s(server_.tasksMonitor_);
      server_.tasks_.erase(this);
      server_.tasksMonitor_.notify();
    }
  }

 private:
  TAcceptQueueServer& server_;
  friend class TAcceptQueueServer;

  shared_ptr<TProcessor> processor_;
  shared_ptr<TProtocol> input_;
  shared_ptr<TProtocol> output_;
  shared_ptr<TTransport> transport_;
};

TAcceptQueueServer::TAcceptQueueServer(const boost::shared_ptr<TProcessor>& processor,
    const boost::shared_ptr<TServerTransport>& serverTransport,
    const boost::shared_ptr<TTransportFactory>& transportFactory,
    const boost::shared_ptr<TProtocolFactory>& protocolFactory,
    const boost::shared_ptr<ThreadFactory>& threadFactory,
    int32_t maxTasks)
    : TServer(processor, serverTransport, transportFactory, protocolFactory),
      threadFactory_(threadFactory), maxTasks_(maxTasks) {
  init();
}

void TAcceptQueueServer::init() {
  stop_ = false;
  metrics_enabled_ = false;
  queue_size_metric_ = nullptr;

  if (!threadFactory_) {
    threadFactory_.reset(new PlatformThreadFactory);
  }
}

// New.
void TAcceptQueueServer::SetupConnection(boost::shared_ptr<TTransport> client) {
  if (metrics_enabled_) queue_size_metric_->Increment(-1);
  shared_ptr<TTransport> inputTransport;
  shared_ptr<TTransport> outputTransport;
  try {
    inputTransport = inputTransportFactory_->getTransport(client);
    outputTransport = outputTransportFactory_->getTransport(client);
    shared_ptr<TProtocol> inputProtocol =
        inputProtocolFactory_->getProtocol(inputTransport);
    shared_ptr<TProtocol> outputProtocol =
        outputProtocolFactory_->getProtocol(outputTransport);

    shared_ptr<TProcessor> processor =
        getProcessor(inputProtocol, outputProtocol, client);

    TAcceptQueueServer::Task* task = new TAcceptQueueServer::Task(
        *this, processor, inputProtocol, outputProtocol, client);

    // Create a task
    shared_ptr<Runnable> runnable = shared_ptr<Runnable>(task);

    // Create a thread for this task
    shared_ptr<Thread> thread = shared_ptr<Thread>(threadFactory_->newThread(runnable));

    // Insert thread into the set of threads
    {
      Synchronized s(tasksMonitor_);
      while (maxTasks_ > 0 && tasks_.size() >= maxTasks_) {
        tasksMonitor_.wait();
      }
      tasks_.insert(task);
    }

    // Start the thread!
    thread->start();
  } catch (TException& tx) {
    if (inputTransport != nullptr) {
      inputTransport->close();
    }
    if (outputTransport != nullptr) {
      outputTransport->close();
    }
    if (client != nullptr) {
      client->close();
    }
    string errStr = string("TAcceptQueueServer: Caught TException: ") + tx.what();
    GlobalOutput(errStr.c_str());
  } catch (string s) {
    if (inputTransport != nullptr) {
      inputTransport->close();
    }
    if (outputTransport != nullptr) {
      outputTransport->close();
    }
    if (client != nullptr) {
      client->close();
    }
    string errStr = "TAcceptQueueServer: Unknown exception: " + s;
    GlobalOutput(errStr.c_str());
  }
}

void TAcceptQueueServer::serve() {
  // Start the server listening
  serverTransport_->listen();

  // Run the preServe event
  if (eventHandler_ != nullptr) {
    eventHandler_->preServe();
  }

  if (FLAGS_accepted_cnxn_setup_thread_pool_size > 1) {
    LOG(WARNING) << "connection_setup_thread_pool_size is set to "
                 << FLAGS_accepted_cnxn_setup_thread_pool_size
                 << ". Values greater than 1 are untested and might exhibit "
                    "unpredictable behavior and/or cause crashes.";
  }
  // New - this is the thread pool used to process the internal accept queue.
  // TODO: IMPALA-7565: Make sure the related thrift code is thread safe and subsequently
  // enable multi-threading by default.
  ThreadPool<shared_ptr<TTransport>> connection_setup_pool("setup-server", "setup-worker",
      FLAGS_accepted_cnxn_setup_thread_pool_size, FLAGS_accepted_cnxn_queue_depth,
      [this](int tid, const shared_ptr<TTransport>& item) {
        this->SetupConnection(item);
      });
  // Initialize the thread pool
  Status status = connection_setup_pool.Init();
  if (!status.ok()) {
    status.AddDetail("TAcceptQueueServer: thread pool could not start.");
    string errStr = status.GetDetail();
    GlobalOutput(errStr.c_str());
    stop_ = true;
  }

  while (!stop_) {
    try {
      // Fetch client from server
      shared_ptr<TTransport> client = serverTransport_->accept();

      // New - the work done to setup the connection has been moved to SetupConnection.
      if (!connection_setup_pool.Offer(std::move(client))) {
        string errStr = string("TAcceptQueueServer: thread pool unexpectedly shut down.");
        GlobalOutput(errStr.c_str());
        stop_ = true;
        break;
      }
      if (metrics_enabled_) queue_size_metric_->Increment(1);
    } catch (TTransportException& ttx) {
      if (!stop_ || ttx.getType() != TTransportException::INTERRUPTED) {
        string errStr =
            string("TAcceptQueueServer: TServerTransport died on accept: ") + ttx.what();
        GlobalOutput(errStr.c_str());
      }
      continue;
    } catch (TException& tx) {
      string errStr = string("TAcceptQueueServer: Caught TException: ") + tx.what();
      GlobalOutput(errStr.c_str());
      continue;
    } catch (string s) {
      string errStr = "TAcceptQueueServer: Unknown exception: " + s;
      GlobalOutput(errStr.c_str());
      break;
    }
  }

  // If stopped manually, make sure to close server transport
  if (stop_) {
    try {
      serverTransport_->close();
      connection_setup_pool.Shutdown();
    } catch (TException& tx) {
      string errStr = string("TAcceptQueueServer: Exception shutting down: ") + tx.what();
      GlobalOutput(errStr.c_str());
    }
    try {
      Synchronized s(tasksMonitor_);
      while (!tasks_.empty()) {
        tasksMonitor_.wait();
      }
    } catch (TException& tx) {
      string errStr =
          string("TAcceptQueueServer: Exception joining workers: ") + tx.what();
      GlobalOutput(errStr.c_str());
    }
    stop_ = false;
  }
}

void TAcceptQueueServer::InitMetrics(MetricGroup* metrics, const string& key_prefix) {
  DCHECK(metrics != nullptr);
  stringstream queue_size_ss;
  queue_size_ss << key_prefix << ".connection-setup-queue-size";
  queue_size_metric_ = metrics->AddGauge(queue_size_ss.str(), 0);
  metrics_enabled_ = true;
}

} // namespace server
} // namespace thrift
} // namespace apache
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net>     *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   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 Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#ifndef _PreComp_

# include <boost/uuid/uuid_io.hpp>
#endif
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <gp_Circ.hxx>
#include <Geom_Circle.hxx>

#include <App/Material.h>

#include <Base/Console.h>
#include <Base/Vector3D.h>
#include <Base/VectorPy.h>
#include <Base/GeometryPyCXX.h>

#include "DrawUtil.h"
#include "Geometry.h"
#include "Cosmetic.h"
#include "CosmeticEdgePy.h"
#include "CosmeticEdgePy.cpp"

using namespace TechDraw;

// returns a string which represents the object e.g. when printed in python
std::string CosmeticEdgePy::representation(void) const
{
    std::stringstream ss;
    ss << "<CosmeticEdge object> at " << std::hex << this;
    return ss.str();
//    return "<CosmeticEdge object>";
}

PyObject *CosmeticEdgePy::PyMake(struct _typeobject *, PyObject *, PyObject *)  // Python wrapper
{
    // never create such objects with the constructor
    PyErr_SetString(PyExc_RuntimeError,
        "You cannot create an instance of the abstract class 'CosmeticEdge'.");
    return 0;
}

// constructor method
int CosmeticEdgePy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
{
    return 0;
}

//From Part::GeometryPy.cpp
PyObject* CosmeticEdgePy::clone(PyObject *args)
{
    if (!PyArg_ParseTuple(args, ""))
        return NULL;

    TechDraw::CosmeticEdge* geom = this->getCosmeticEdgePtr();
    PyTypeObject* type = this->GetType();
    PyObject* cpy = 0;
    // let the type object decide
    if (type->tp_new)
        cpy = type->tp_new(type, this, 0);
    if (!cpy) {
        PyErr_SetString(PyExc_TypeError, "failed to create clone of CosmeticEdge");
        return 0;
    }

    TechDraw::CosmeticEdgePy* geompy = static_cast<TechDraw::CosmeticEdgePy*>(cpy);
    // the PyMake function must have created the corresponding instance of the 'CosmeticEdge' subclass
    // so delete it now to avoid a memory leak
    if (geompy->_pcTwinPointer) {
        TechDraw::CosmeticEdge* clone = static_cast<TechDraw::CosmeticEdge*>(geompy->_pcTwinPointer);
        delete clone;
    }
    geompy->_pcTwinPointer = geom->clone();
    return cpy;
}

PyObject* CosmeticEdgePy::copy(PyObject *args)
{
    if (!PyArg_ParseTuple(args, ""))
        return NULL;

    TechDraw::CosmeticEdge* geom = this->getCosmeticEdgePtr();
    PyTypeObject* type = this->GetType();
    PyObject* cpy = 0;
    // let the type object decide
    if (type->tp_new)
        cpy = type->tp_new(type, this, 0);
    if (!cpy) {
        PyErr_SetString(PyExc_TypeError, "failed to create copy of CosmeticEdge");
        return 0;
    }

    TechDraw::CosmeticEdgePy* geompy = static_cast<TechDraw::CosmeticEdgePy*>(cpy);
    // the PyMake function must have created the corresponding instance of the 'CosmeticEdge' subclass
    // so delete it now to avoid a memory leak
    if (geompy->_pcTwinPointer) {
        TechDraw::CosmeticEdge* copy = static_cast<TechDraw::CosmeticEdge*>(geompy->_pcTwinPointer);
        delete copy;
    }
    geompy->_pcTwinPointer = geom->copy();
    return cpy;
}

void CosmeticEdgePy::setFormat(Py::Object arg)
{
    PyObject* pTuple = arg.ptr();
    int style = 1;
    double weight = 0.50;
    double red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
    App::Color c(red, blue, green, alpha);
    bool visible = 1;

    TechDraw::CosmeticEdge* ce = this->getCosmeticEdgePtr();
    if (PyTuple_Check(pTuple)) {
        int tSize = (int) PyTuple_Size(pTuple);
        if (tSize > 3) {
            PyObject* pStyle = PyTuple_GetItem(pTuple,0);
            style = (int) PyLong_AsLong(pStyle);
            PyObject* pWeight = PyTuple_GetItem(pTuple,1);
            weight = PyFloat_AsDouble(pWeight);
            PyObject* pColor = PyTuple_GetItem(pTuple,2);
            c = DrawUtil::pyTupleToColor(pColor);
            PyObject* pVisible = PyTuple_GetItem(pTuple,3);
            visible = (bool) PyLong_AsLong(pVisible);

            ce->m_format.m_style = style;
            ce->m_format.m_weight = weight;
            ce->m_format.m_color = c;
            ce->m_format.m_visible = visible;
        }
    } else {
        Base::Console().Error("CEPI::setFormat - not a tuple!\n");
    }
}

Py::Object CosmeticEdgePy::getFormat(void) const
{
    TechDraw::CosmeticEdge* ce = this->getCosmeticEdgePtr();

    PyObject* pStyle = PyLong_FromLong((long) ce->m_format.m_style);
    PyObject* pWeight = PyFloat_FromDouble(ce->m_format.m_weight);
    PyObject* pColor = DrawUtil::colorToPyTuple(ce->m_format.m_color);
    PyObject* pVisible = PyBool_FromLong((long) ce->m_format.m_visible);

    PyObject* result = PyTuple_New(4);

    PyTuple_SET_ITEM(result, 0, pStyle);
    PyTuple_SET_ITEM(result, 1, pWeight);
    PyTuple_SET_ITEM(result, 2, pColor);
    PyTuple_SET_ITEM(result, 3, pVisible);

    return Py::asObject(result);
}

Py::String CosmeticEdgePy::getTag(void) const
{
    std::string tmp = boost::uuids::to_string(getCosmeticEdgePtr()->getTag());
    return Py::String(tmp);
}

//Py::String CosmeticEdgePy::getOwner(void) const
//{
////    std::string tmp = boost::uuids::to_string(getCosmeticEdgePtr()->getOwner());
//    std::string tmp = "not implemented yet";
//    return Py::String(tmp);
//}

//TODO: make BaseGeom py-aware or convert TD geometry to ??Part::Geometry2d?? or other
//      py-aware class.
//Py::Object CosmeticEdgePy::getGeometry(void) const
//{
////    TechDraw::BaseGeom* bg = getCosmeticEdgePtr()->m_geometry;
//    Base::Console().Message("Not implemented yet");
//    return Py::asObject(Py_None);
//}

//void CosmeticEdgePy::setGeometry(Py::Object arg)
//{
//    Base::Console().Message("Not implemented yet");
//    PyObject* p = arg.ptr();
//    if (PyObject_TypeCheck(p, &(TechDraw::BaseGeomPy::Type))) {
//        //TODO
//    } else {
//        std::string error = std::string("type must be 'BaseGeom', not ");
//        error += p->ob_type->tp_name;
//        throw Py::TypeError(error);
//    }
//}

Py::Object CosmeticEdgePy::getStart(void) const
{
    Base::Vector3d point = getCosmeticEdgePtr()->permaStart;
    return Py::asObject(new Base::VectorPy(point));
}

void CosmeticEdgePy::setStart(Py::Object arg)
{
    PyObject* p = arg.ptr();
    Base::Vector3d pNew;
    if (PyObject_TypeCheck(p, &(Base::VectorPy::Type))) {
        pNew = static_cast<Base::VectorPy*>(p)->value();
    }
    else if (PyObject_TypeCheck(p, &PyTuple_Type)) {
        pNew = Base::getVectorFromTuple<double>(p);
    }
    else {
        std::string error = std::string("type must be 'Vector', not ");
        error += p->ob_type->tp_name;
        throw Py::TypeError(error);
    }

    pNew = DrawUtil::invertY(pNew);
    Base::Vector3d pEnd = getCosmeticEdgePtr()->permaEnd;
    pEnd = DrawUtil::invertY(pEnd);
    gp_Pnt gp1(pNew.x,pNew.y,pNew.z);
    gp_Pnt gp2(pEnd.x,pEnd.y,pEnd.z);
    TopoDS_Edge e = BRepBuilderAPI_MakeEdge(gp1, gp2);
    auto oldGeom = getCosmeticEdgePtr()->m_geometry;
    getCosmeticEdgePtr()->m_geometry = TechDraw::BaseGeom::baseFactory(e);
    getCosmeticEdgePtr()->permaStart = pNew;
    delete oldGeom;
}

Py::Object CosmeticEdgePy::getEnd(void) const
{
    Base::Vector3d point = getCosmeticEdgePtr()->permaEnd;
    return Py::asObject(new Base::VectorPy(point));
}

void CosmeticEdgePy::setEnd(Py::Object arg)
{
    PyObject* p = arg.ptr();
    Base::Vector3d pNew;
    if (PyObject_TypeCheck(p, &(Base::VectorPy::Type))) {
        pNew = static_cast<Base::VectorPy*>(p)->value();
    }
    else if (PyObject_TypeCheck(p, &PyTuple_Type)) {
        pNew = Base::getVectorFromTuple<double>(p);
    }
    else {
        std::string error = std::string("type must be 'Vector', not ");
        error += p->ob_type->tp_name;
        throw Py::TypeError(error);
    }

    pNew = DrawUtil::invertY(pNew);
    Base::Vector3d pStart = getCosmeticEdgePtr()->permaStart;
    pStart = DrawUtil::invertY(pStart);
    gp_Pnt gp1(pNew.x,pNew.y,pNew.z);
    gp_Pnt gp2(pStart.x,pStart.y,pStart.z);
    TopoDS_Edge e = BRepBuilderAPI_MakeEdge(gp2, gp1);
    auto oldGeom = getCosmeticEdgePtr()->m_geometry;
    getCosmeticEdgePtr()->m_geometry = TechDraw::BaseGeom::baseFactory(e);
    getCosmeticEdgePtr()->permaEnd = pNew;
    delete oldGeom;
}

Py::Object CosmeticEdgePy::getRadius(void) const
{
    double r = getCosmeticEdgePtr()->permaRadius;
    return Py::asObject(PyFloat_FromDouble(r));
}

void CosmeticEdgePy::setRadius(Py::Object arg)
{
    //TODO: check if the edge has a radius attrib
    PyObject* p = arg.ptr();
    double r;
    if (PyObject_TypeCheck(p, &PyFloat_Type)) {
        r = PyFloat_AsDouble(p);
    }
    else if (PyObject_TypeCheck(p, &PyLong_Type)) {
        r = (double) PyLong_AsLong(p);
    }
    else {
        std::string error = std::string("type must be 'Float' or 'Int', not ");
        error += p->ob_type->tp_name;
        throw Py::TypeError(error);
    }

    getCosmeticEdgePtr()->permaRadius = r;
    auto oldGeom = getCosmeticEdgePtr()->m_geometry;
    getCosmeticEdgePtr()->m_geometry = new TechDraw::Circle(getCosmeticEdgePtr()->permaStart, r);
    delete oldGeom;
}

Py::Object CosmeticEdgePy::getCenter(void) const
{
    Base::Vector3d point = getCosmeticEdgePtr()->permaStart;
    return Py::asObject(new Base::VectorPy(point));
}

void CosmeticEdgePy::setCenter(Py::Object arg)
{
    PyObject* p = arg.ptr();
    Base::Vector3d pNew;
    if (PyObject_TypeCheck(p, &(Base::VectorPy::Type))) {
        pNew = static_cast<Base::VectorPy*>(p)->value();
    }
    else if (PyObject_TypeCheck(p, &PyTuple_Type)) {
        pNew = Base::getVectorFromTuple<double>(p);
    }
    else {
        std::string error = std::string("type must be 'Vector', not ");
        error += p->ob_type->tp_name;
        throw Py::TypeError(error);
    }

    pNew = DrawUtil::invertY(pNew);
    auto oldGeom = getCosmeticEdgePtr()->m_geometry;
    TechDraw::Circle* oldCircle = dynamic_cast<TechDraw::Circle*>(oldGeom);

    getCosmeticEdgePtr()->permaStart = pNew;
    getCosmeticEdgePtr()->permaEnd = pNew;
    getCosmeticEdgePtr()->permaRadius = oldCircle->radius;
    getCosmeticEdgePtr()->m_geometry = new TechDraw::Circle(getCosmeticEdgePtr()->permaStart, oldCircle->radius);
    delete oldGeom;
}

PyObject *CosmeticEdgePy::getCustomAttributes(const char* /*attr*/) const
{
    return 0;
}

int CosmeticEdgePy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
    return 0;
}

<commit_msg>[TD]CosmeticEdge type guards<commit_after>/***************************************************************************
 *   Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net>     *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   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 Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#ifndef _PreComp_

# include <boost/uuid/uuid_io.hpp>
#endif
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <gp_Circ.hxx>
#include <Geom_Circle.hxx>

#include <App/Material.h>

#include <Base/Console.h>
#include <Base/Vector3D.h>
#include <Base/VectorPy.h>
#include <Base/GeometryPyCXX.h>

#include "DrawUtil.h"
#include "Geometry.h"
#include "Cosmetic.h"
#include "CosmeticEdgePy.h"
#include "CosmeticEdgePy.cpp"

using namespace TechDraw;

// returns a string which represents the object e.g. when printed in python
std::string CosmeticEdgePy::representation(void) const
{
    std::stringstream ss;
    ss << "<CosmeticEdge object> at " << std::hex << this;
    return ss.str();
//    return "<CosmeticEdge object>";
}

PyObject *CosmeticEdgePy::PyMake(struct _typeobject *, PyObject *, PyObject *)  // Python wrapper
{
    // never create such objects with the constructor
    PyErr_SetString(PyExc_RuntimeError,
        "You cannot create an instance of the abstract class 'CosmeticEdge'.");
    return 0;
}

// constructor method
int CosmeticEdgePy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
{
    return 0;
}

//From Part::GeometryPy.cpp
PyObject* CosmeticEdgePy::clone(PyObject *args)
{
    if (!PyArg_ParseTuple(args, ""))
        return NULL;

    TechDraw::CosmeticEdge* geom = this->getCosmeticEdgePtr();
    PyTypeObject* type = this->GetType();
    PyObject* cpy = 0;
    // let the type object decide
    if (type->tp_new)
        cpy = type->tp_new(type, this, 0);
    if (!cpy) {
        PyErr_SetString(PyExc_TypeError, "failed to create clone of CosmeticEdge");
        return 0;
    }

    TechDraw::CosmeticEdgePy* geompy = static_cast<TechDraw::CosmeticEdgePy*>(cpy);
    // the PyMake function must have created the corresponding instance of the 'CosmeticEdge' subclass
    // so delete it now to avoid a memory leak
    if (geompy->_pcTwinPointer) {
        TechDraw::CosmeticEdge* clone = static_cast<TechDraw::CosmeticEdge*>(geompy->_pcTwinPointer);
        delete clone;
    }
    geompy->_pcTwinPointer = geom->clone();
    return cpy;
}

PyObject* CosmeticEdgePy::copy(PyObject *args)
{
    if (!PyArg_ParseTuple(args, ""))
        return NULL;

    TechDraw::CosmeticEdge* geom = this->getCosmeticEdgePtr();
    PyTypeObject* type = this->GetType();
    PyObject* cpy = 0;
    // let the type object decide
    if (type->tp_new)
        cpy = type->tp_new(type, this, 0);
    if (!cpy) {
        PyErr_SetString(PyExc_TypeError, "failed to create copy of CosmeticEdge");
        return 0;
    }

    TechDraw::CosmeticEdgePy* geompy = static_cast<TechDraw::CosmeticEdgePy*>(cpy);
    // the PyMake function must have created the corresponding instance of the 'CosmeticEdge' subclass
    // so delete it now to avoid a memory leak
    if (geompy->_pcTwinPointer) {
        TechDraw::CosmeticEdge* copy = static_cast<TechDraw::CosmeticEdge*>(geompy->_pcTwinPointer);
        delete copy;
    }
    geompy->_pcTwinPointer = geom->copy();
    return cpy;
}

void CosmeticEdgePy::setFormat(Py::Object arg)
{
    PyObject* pTuple = arg.ptr();
    int style = 1;
    double weight = 0.50;
    double red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
    App::Color c(red, blue, green, alpha);
    bool visible = 1;

    TechDraw::CosmeticEdge* ce = this->getCosmeticEdgePtr();
    if (PyTuple_Check(pTuple)) {
        int tSize = (int) PyTuple_Size(pTuple);
        if (tSize > 3) {
            PyObject* pStyle = PyTuple_GetItem(pTuple,0);
            style = (int) PyLong_AsLong(pStyle);
            PyObject* pWeight = PyTuple_GetItem(pTuple,1);
            weight = PyFloat_AsDouble(pWeight);
            PyObject* pColor = PyTuple_GetItem(pTuple,2);
            c = DrawUtil::pyTupleToColor(pColor);
            PyObject* pVisible = PyTuple_GetItem(pTuple,3);
            visible = (bool) PyLong_AsLong(pVisible);

            ce->m_format.m_style = style;
            ce->m_format.m_weight = weight;
            ce->m_format.m_color = c;
            ce->m_format.m_visible = visible;
        }
    } else {
        Base::Console().Error("CEPI::setFormat - not a tuple!\n");
    }
}

Py::Object CosmeticEdgePy::getFormat(void) const
{
    TechDraw::CosmeticEdge* ce = this->getCosmeticEdgePtr();

    PyObject* pStyle = PyLong_FromLong((long) ce->m_format.m_style);
    PyObject* pWeight = PyFloat_FromDouble(ce->m_format.m_weight);
    PyObject* pColor = DrawUtil::colorToPyTuple(ce->m_format.m_color);
    PyObject* pVisible = PyBool_FromLong((long) ce->m_format.m_visible);

    PyObject* result = PyTuple_New(4);

    PyTuple_SET_ITEM(result, 0, pStyle);
    PyTuple_SET_ITEM(result, 1, pWeight);
    PyTuple_SET_ITEM(result, 2, pColor);
    PyTuple_SET_ITEM(result, 3, pVisible);

    return Py::asObject(result);
}

Py::String CosmeticEdgePy::getTag(void) const
{
    std::string tmp = boost::uuids::to_string(getCosmeticEdgePtr()->getTag());
    return Py::String(tmp);
}

//Py::String CosmeticEdgePy::getOwner(void) const
//{
////    std::string tmp = boost::uuids::to_string(getCosmeticEdgePtr()->getOwner());
//    std::string tmp = "not implemented yet";
//    return Py::String(tmp);
//}

//TODO: make BaseGeom py-aware or convert TD geometry to ??Part::Geometry2d?? or other
//      py-aware class.
//Py::Object CosmeticEdgePy::getGeometry(void) const
//{
////    TechDraw::BaseGeom* bg = getCosmeticEdgePtr()->m_geometry;
//    Base::Console().Message("Not implemented yet");
//    return Py::asObject(Py_None);
//}

//void CosmeticEdgePy::setGeometry(Py::Object arg)
//{
//    Base::Console().Message("Not implemented yet");
//    PyObject* p = arg.ptr();
//    if (PyObject_TypeCheck(p, &(TechDraw::BaseGeomPy::Type))) {
//        //TODO
//    } else {
//        std::string error = std::string("type must be 'BaseGeom', not ");
//        error += p->ob_type->tp_name;
//        throw Py::TypeError(error);
//    }
//}

Py::Object CosmeticEdgePy::getStart(void) const
{
    Base::Vector3d point = getCosmeticEdgePtr()->permaStart;
    return Py::asObject(new Base::VectorPy(point));
}

void CosmeticEdgePy::setStart(Py::Object arg)
{
    PyObject* p = arg.ptr();
    Base::Vector3d pNew;
    if (PyObject_TypeCheck(p, &(Base::VectorPy::Type))) {
        pNew = static_cast<Base::VectorPy*>(p)->value();
    }
    else if (PyObject_TypeCheck(p, &PyTuple_Type)) {
        pNew = Base::getVectorFromTuple<double>(p);
    }
    else {
        std::string error = std::string("type must be 'Vector', not ");
        error += p->ob_type->tp_name;
        throw Py::TypeError(error);
    }

    pNew = DrawUtil::invertY(pNew);
    Base::Vector3d pEnd = getCosmeticEdgePtr()->permaEnd;
    pEnd = DrawUtil::invertY(pEnd);
    gp_Pnt gp1(pNew.x,pNew.y,pNew.z);
    gp_Pnt gp2(pEnd.x,pEnd.y,pEnd.z);
    TopoDS_Edge e = BRepBuilderAPI_MakeEdge(gp1, gp2);
    auto oldGeom = getCosmeticEdgePtr()->m_geometry;
    getCosmeticEdgePtr()->m_geometry = TechDraw::BaseGeom::baseFactory(e);
    getCosmeticEdgePtr()->permaStart = pNew;
    delete oldGeom;
}

Py::Object CosmeticEdgePy::getEnd(void) const
{
    Base::Vector3d point = getCosmeticEdgePtr()->permaEnd;
    return Py::asObject(new Base::VectorPy(point));
}

void CosmeticEdgePy::setEnd(Py::Object arg)
{
    PyObject* p = arg.ptr();
    Base::Vector3d pNew;
    if (PyObject_TypeCheck(p, &(Base::VectorPy::Type))) {
        pNew = static_cast<Base::VectorPy*>(p)->value();
    }
    else if (PyObject_TypeCheck(p, &PyTuple_Type)) {
        pNew = Base::getVectorFromTuple<double>(p);
    }
    else {
        std::string error = std::string("type must be 'Vector', not ");
        error += p->ob_type->tp_name;
        throw Py::TypeError(error);
    }

    pNew = DrawUtil::invertY(pNew);
    Base::Vector3d pStart = getCosmeticEdgePtr()->permaStart;
    pStart = DrawUtil::invertY(pStart);
    gp_Pnt gp1(pNew.x,pNew.y,pNew.z);
    gp_Pnt gp2(pStart.x,pStart.y,pStart.z);
    TopoDS_Edge e = BRepBuilderAPI_MakeEdge(gp2, gp1);
    auto oldGeom = getCosmeticEdgePtr()->m_geometry;
    getCosmeticEdgePtr()->m_geometry = TechDraw::BaseGeom::baseFactory(e);
    getCosmeticEdgePtr()->permaEnd = pNew;
    delete oldGeom;
}

Py::Object CosmeticEdgePy::getRadius(void) const
{
    TechDraw::GeomType gt = getCosmeticEdgePtr()->m_geometry->geomType;
    if ( (gt != TechDraw::GeomType::CIRCLE) &&
         (gt != TechDraw::GeomType::ARCOFCIRCLE) ) {
        std::string error = "not a cirle. Can not set radius";
        throw Py::TypeError(error);
    }
    double r = getCosmeticEdgePtr()->permaRadius;
    return Py::asObject(PyFloat_FromDouble(r));
}

void CosmeticEdgePy::setRadius(Py::Object arg)
{
    TechDraw::GeomType gt = getCosmeticEdgePtr()->m_geometry->geomType;
    PyObject* p = arg.ptr();
    if ( (gt != TechDraw::GeomType::CIRCLE) &&
         (gt != TechDraw::GeomType::ARCOFCIRCLE) ) {
        std::string error = std::string(p->ob_type->tp_name);
        error += " is not a cirle. Can not set radius";
        throw Py::TypeError(error);
    }

    double r;
    if (PyObject_TypeCheck(p, &PyFloat_Type)) {
        r = PyFloat_AsDouble(p);
    }
    else if (PyObject_TypeCheck(p, &PyLong_Type)) {
        r = (double) PyLong_AsLong(p);
    }
    else {
        std::string error = std::string("type must be 'Float' or 'Int', not ");
        error += p->ob_type->tp_name;
        throw Py::TypeError(error);
    }

    getCosmeticEdgePtr()->permaRadius = r;
    auto oldGeom = getCosmeticEdgePtr()->m_geometry;
    getCosmeticEdgePtr()->m_geometry = new TechDraw::Circle(getCosmeticEdgePtr()->permaStart, r);
    delete oldGeom;
}

Py::Object CosmeticEdgePy::getCenter(void) const
{
    TechDraw::GeomType gt = getCosmeticEdgePtr()->m_geometry->geomType;
    if ( (gt != TechDraw::GeomType::CIRCLE) &&
         (gt != TechDraw::GeomType::ARCOFCIRCLE) ) {
        std::string error = "not a cirle. Can not get center";
        throw Py::TypeError(error);
    }
    Base::Vector3d point = getCosmeticEdgePtr()->permaStart;
    return Py::asObject(new Base::VectorPy(point));
}

void CosmeticEdgePy::setCenter(Py::Object arg)
{
    TechDraw::GeomType gt = getCosmeticEdgePtr()->m_geometry->geomType;
    PyObject* p = arg.ptr();
    if ( (gt != TechDraw::GeomType::CIRCLE) &&
         (gt != TechDraw::GeomType::ARCOFCIRCLE) ) {
        std::string error = std::string(p->ob_type->tp_name);
        error += " is not a cirle. Can not set center";
        throw Py::TypeError(error);
    }

//    PyObject* p = arg.ptr();
    Base::Vector3d pNew;
    if (PyObject_TypeCheck(p, &(Base::VectorPy::Type))) {
        pNew = static_cast<Base::VectorPy*>(p)->value();
    }
    else if (PyObject_TypeCheck(p, &PyTuple_Type)) {
        pNew = Base::getVectorFromTuple<double>(p);
    }
    else {
        std::string error = std::string("type must be 'Vector', not ");
        error += p->ob_type->tp_name;
        throw Py::TypeError(error);
    }

    pNew = DrawUtil::invertY(pNew);
    auto oldGeom = getCosmeticEdgePtr()->m_geometry;
    TechDraw::Circle* oldCircle = dynamic_cast<TechDraw::Circle*>(oldGeom);

    getCosmeticEdgePtr()->permaStart = pNew;
    getCosmeticEdgePtr()->permaEnd = pNew;
    getCosmeticEdgePtr()->permaRadius = oldCircle->radius;
    getCosmeticEdgePtr()->m_geometry = new TechDraw::Circle(getCosmeticEdgePtr()->permaStart, oldCircle->radius);
    delete oldGeom;
}

PyObject *CosmeticEdgePy::getCustomAttributes(const char* /*attr*/) const
{
    return 0;
}

int CosmeticEdgePy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
    return 0;
}

<|endoftext|>


<commit_before>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Graphics/Formats/MeshLoader.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Graphics/Material.hpp>
#include <Nazara/Graphics/Model.hpp>
#include <Nazara/Graphics/SkeletalModel.hpp>
#include <Nazara/Utility/MaterialData.hpp>
#include <Nazara/Utility/Mesh.hpp>
#include <memory>
#include <Nazara/Graphics/Debug.hpp>

namespace Nz
{
	namespace
	{
		void LoadMaterials(Model* model, const ModelParameters& parameters)
		{
			unsigned int matCount = model->GetMaterialCount();

			for (unsigned int i = 0; i < matCount; ++i)
			{
				const ParameterList& matData = model->GetMesh()->GetMaterialData(i);

				String filePath;
				if (matData.GetStringParameter(MaterialData::FilePath, &filePath))
				{
					MaterialRef material = Material::New();
					if (material->LoadFromFile(filePath, parameters.material))
						model->SetMaterial(i, std::move(material));
					else
						NazaraWarning("Failed to load material from file " + String::Number(i));
				}
				else if (matData.HasParameter(MaterialData::CustomDefined))
				{
					MaterialRef material = Material::New();
					material->BuildFromParameters(matData, parameters.material);

					model->SetMaterial(i, std::move(material));
				}
			}
		}

		Ternary CheckStatic(Stream& stream, const ModelParameters& parameters)
		{
			NazaraUnused(stream);

			bool skip;
			if (parameters.custom.GetBooleanParameter("SkipNativeMeshLoader", &skip) && skip)
				return Ternary_False;

			return Ternary_Unknown;
		}

		bool LoadStatic(Model* model, Stream& stream, const ModelParameters& parameters)
		{
			NazaraUnused(parameters);

			MeshRef mesh = Mesh::New();
			if (!mesh->LoadFromStream(stream, parameters.mesh))
			{
				NazaraError("Failed to load model mesh");
				return false;
			}

			if (mesh->IsAnimable())
			{
				NazaraError("Can't load animated mesh into static model");
				return false;
			}

			model->Reset();
			model->SetMesh(mesh);

			if (parameters.loadMaterials)
				LoadMaterials(model, parameters);

			return true;
		}

		Ternary CheckAnimated(Stream& stream, const SkeletalModelParameters& parameters)
		{
			NazaraUnused(stream);

			bool skip;
			if (parameters.custom.GetBooleanParameter("SkipNativeAnimatedMeshLoader", &skip) && skip)
				return Ternary_False;

			return Ternary_Unknown;
		}

		bool LoadAnimated(SkeletalModel* model, Stream& stream, const SkeletalModelParameters& parameters)
		{
			NazaraUnused(parameters);

			MeshRef mesh = Mesh::New();
			if (!mesh->LoadFromStream(stream, parameters.mesh))
			{
				NazaraError("Failed to load model mesh");
				return false;
			}

			if (!mesh->IsAnimable())
			{
				NazaraError("Can't load static mesh into animated model");
				return false;
			}

			model->Reset();
			model->SetMesh(mesh);

			if (parameters.loadMaterials)
				LoadMaterials(model, parameters);

			return true;
		}
	}

	namespace Loaders
	{
		void RegisterMesh()
		{
			ModelLoader::RegisterLoader(MeshLoader::IsExtensionSupported, CheckStatic, LoadStatic);
			SkeletalModelLoader::RegisterLoader(MeshLoader::IsExtensionSupported, CheckAnimated, LoadAnimated);
		}

		void UnregisterMesh()
		{
			ModelLoader::UnregisterLoader(MeshLoader::IsExtensionSupported, CheckStatic, LoadStatic);
			SkeletalModelLoader::UnregisterLoader(MeshLoader::IsExtensionSupported, CheckAnimated, LoadAnimated);
		}
	}
}

<commit_msg>Default behaviour without precision on name<commit_after>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Graphics/Formats/MeshLoader.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Graphics/Material.hpp>
#include <Nazara/Graphics/Model.hpp>
#include <Nazara/Graphics/SkeletalModel.hpp>
#include <Nazara/Utility/MaterialData.hpp>
#include <Nazara/Utility/Mesh.hpp>
#include <memory>
#include <Nazara/Graphics/Debug.hpp>

namespace Nz
{
	namespace
	{
		void LoadMaterials(Model* model, const ModelParameters& parameters)
		{
			unsigned int matCount = model->GetMaterialCount();

			for (unsigned int i = 0; i < matCount; ++i)
			{
				const ParameterList& matData = model->GetMesh()->GetMaterialData(i);

				String filePath;
				if (matData.GetStringParameter(MaterialData::FilePath, &filePath))
				{
					if (!File::Exists(filePath))
					{
						NazaraWarning("Shader name does not refer to an existing file, \".tga\" is used by default");
						filePath += ".tga";
					}

					MaterialRef material = Material::New();
					if (material->LoadFromFile(filePath, parameters.material))
						model->SetMaterial(i, std::move(material));
					else
						NazaraWarning("Failed to load material from file " + String::Number(i));
				}
				else if (matData.HasParameter(MaterialData::CustomDefined))
				{
					MaterialRef material = Material::New();
					material->BuildFromParameters(matData, parameters.material);

					model->SetMaterial(i, std::move(material));
				}
			}
		}

		Ternary CheckStatic(Stream& stream, const ModelParameters& parameters)
		{
			NazaraUnused(stream);

			bool skip;
			if (parameters.custom.GetBooleanParameter("SkipNativeMeshLoader", &skip) && skip)
				return Ternary_False;

			return Ternary_Unknown;
		}

		bool LoadStatic(Model* model, Stream& stream, const ModelParameters& parameters)
		{
			NazaraUnused(parameters);

			MeshRef mesh = Mesh::New();
			if (!mesh->LoadFromStream(stream, parameters.mesh))
			{
				NazaraError("Failed to load model mesh");
				return false;
			}

			if (mesh->IsAnimable())
			{
				NazaraError("Can't load animated mesh into static model");
				return false;
			}

			model->Reset();
			model->SetMesh(mesh);

			if (parameters.loadMaterials)
				LoadMaterials(model, parameters);

			return true;
		}

		Ternary CheckAnimated(Stream& stream, const SkeletalModelParameters& parameters)
		{
			NazaraUnused(stream);

			bool skip;
			if (parameters.custom.GetBooleanParameter("SkipNativeAnimatedMeshLoader", &skip) && skip)
				return Ternary_False;

			return Ternary_Unknown;
		}

		bool LoadAnimated(SkeletalModel* model, Stream& stream, const SkeletalModelParameters& parameters)
		{
			NazaraUnused(parameters);

			MeshRef mesh = Mesh::New();
			if (!mesh->LoadFromStream(stream, parameters.mesh))
			{
				NazaraError("Failed to load model mesh");
				return false;
			}

			if (!mesh->IsAnimable())
			{
				NazaraError("Can't load static mesh into animated model");
				return false;
			}

			model->Reset();
			model->SetMesh(mesh);

			if (parameters.loadMaterials)
				LoadMaterials(model, parameters);

			return true;
		}
	}

	namespace Loaders
	{
		void RegisterMesh()
		{
			ModelLoader::RegisterLoader(MeshLoader::IsExtensionSupported, CheckStatic, LoadStatic);
			SkeletalModelLoader::RegisterLoader(MeshLoader::IsExtensionSupported, CheckAnimated, LoadAnimated);
		}

		void UnregisterMesh()
		{
			ModelLoader::UnregisterLoader(MeshLoader::IsExtensionSupported, CheckStatic, LoadStatic);
			SkeletalModelLoader::UnregisterLoader(MeshLoader::IsExtensionSupported, CheckAnimated, LoadAnimated);
		}
	}
}

<|endoftext|>


<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "list.h"
#include "simplelist.h"
#include "extArray.h"
#include "stringSpace.h"
#include "HashTable.h"
#include "condor_classad.h"
#include "classad_collection_types.h"
#include "MyString.h"
#include "Set.h"
#include "condor_distribution.h"
#include "file_transfer.h"
#include "extra_param_info.h"
#include "daemon.h"
#include "condor_cred_base.h"
#include "condor_credential.h"
#include "condor_config.h"
#include "condor_transfer_request.h"
#include "log_transaction.h"
#include "killfamily.h"
#include "passwd_cache.h"
#include "proc_family_direct.h"
#include "credential.h"

template class ExtArray<ParamValue>;
template class SimpleList<ClassAd*>;
template class List<char>; 		template class Item<char>;
template class List<int>; 		template class Item<int>;
template class SimpleList<int>;
template class SimpleList<float>;
template class ExtArray<PROC_ID>;
template class ExtArray<char *>;
template class ExtArray<int>;
template class ExtArray<MyString>;
template class ExtArray<StringSpace::SSStringEnt>;
template class ExtArray<StringSpace*>;
template class ExtArray<KillFamily::a_pid>;
template class HashTable<int, BaseCollection*>;
template class HashBucket<int, BaseCollection*>;
template class Set<MyString>;
template class SetElem<MyString>;
template class Set<int>;
template class SetElem<int>;
template class Set<RankedClassAd>;
template class SetElem<RankedClassAd>;
template class HashTable<MyString, int>;
template class HashBucket<MyString,int>;
template class HashTable<MyString, MyString>;
template class HashBucket<MyString, MyString>;
template class HashTable<MyString, KeyCacheEntry*>;
template class Queue<char *>;
template class HashTable<int, FileTransfer *>;
template class HashTable<MyString, FileTransfer *>;
template class HashTable<MyString, ExtraParamInfo *>;
template class HashTable<MyString, group_entry*>;
template class HashTable<MyString, uid_entry*>;
template class HashTable<MyString, CatalogEntry*>;
template class SimpleList<Daemon*>;
template class HashTable<Credential_t, Condor_Credential_B*>;
template class SimpleList<MyString>;
template class SimpleListIterator<MyString>;
template class List<LogRecord>;
template class Item<LogRecord>;
template class HashTable<YourSensitiveString,LogRecordList *>;
template class HashTable<pid_t, ProcFamilyDirectContainer*>;
template class SimpleList <Credential*>;

#if defined(Solaris)
template class ExtArray<long>;
#endif
<commit_msg>Fix for platforms lacking classad external.<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "list.h"
#include "simplelist.h"
#include "extArray.h"
#include "stringSpace.h"
#include "HashTable.h"
#include "condor_classad.h"
#include "classad_collection_types.h"
#include "MyString.h"
#include "Set.h"
#include "condor_distribution.h"
#include "file_transfer.h"
#include "extra_param_info.h"
#include "daemon.h"
#include "condor_cred_base.h"
#include "condor_credential.h"
#include "condor_config.h"
#include "condor_transfer_request.h"
#include "log_transaction.h"
#include "killfamily.h"
#include "passwd_cache.h"
#include "proc_family_direct.h"
#if HAVE_EXT_CLASSADS
#include "credential.h"
#endif

template class ExtArray<ParamValue>;
template class SimpleList<ClassAd*>;
template class List<char>; 		template class Item<char>;
template class List<int>; 		template class Item<int>;
template class SimpleList<int>;
template class SimpleList<float>;
template class ExtArray<PROC_ID>;
template class ExtArray<char *>;
template class ExtArray<int>;
template class ExtArray<MyString>;
template class ExtArray<StringSpace::SSStringEnt>;
template class ExtArray<StringSpace*>;
template class ExtArray<KillFamily::a_pid>;
template class HashTable<int, BaseCollection*>;
template class HashBucket<int, BaseCollection*>;
template class Set<MyString>;
template class SetElem<MyString>;
template class Set<int>;
template class SetElem<int>;
template class Set<RankedClassAd>;
template class SetElem<RankedClassAd>;
template class HashTable<MyString, int>;
template class HashBucket<MyString,int>;
template class HashTable<MyString, MyString>;
template class HashBucket<MyString, MyString>;
template class HashTable<MyString, KeyCacheEntry*>;
template class Queue<char *>;
template class HashTable<int, FileTransfer *>;
template class HashTable<MyString, FileTransfer *>;
template class HashTable<MyString, ExtraParamInfo *>;
template class HashTable<MyString, group_entry*>;
template class HashTable<MyString, uid_entry*>;
template class HashTable<MyString, CatalogEntry*>;
template class SimpleList<Daemon*>;
template class HashTable<Credential_t, Condor_Credential_B*>;
template class SimpleList<MyString>;
template class SimpleListIterator<MyString>;
template class List<LogRecord>;
template class Item<LogRecord>;
template class HashTable<YourSensitiveString,LogRecordList *>;
template class HashTable<pid_t, ProcFamilyDirectContainer*>;

#if HAVE_EXT_CLASSADS
template class SimpleList <Credential*>;
#endif

#if defined(Solaris)
template class ExtArray<long>;
#endif
<|endoftext|>