bool SimbodySimmModel::writeMuscle(Muscle& aMuscle, const ForceSet& aActuatorSet, ofstream& aStream)
{
    aStream << "beginmuscle " << aMuscle.getName() << endl;

    const PathPointSet& pts = aMuscle.getGeometryPath().getPathPointSet();

    aStream << "beginpoints" << endl;
    for (int i = 0; i < pts.getSize(); i++)
    {
        PathPoint& pt = pts.get(i);
        if (pt.getConcreteClassName()==("ConditionalPathPoint")) {
            ConditionalPathPoint* mvp = (ConditionalPathPoint*)(&pt);
            Vec3& attachment = mvp->getLocation();
            double range[]{ mvp->get_range(0), mvp->get_range(1) };
            aStream << attachment[0] << " " << attachment[1] << " " << attachment[2] << " segment " << mvp->getBody().getName();
            
            if (mvp->hasCoordinate()) {
                const Coordinate& coord = mvp->getCoordinate();
                if (coord.getMotionType() == Coordinate::Rotational)
                    aStream << " ranges 1 " << coord.getName() << " (" << range[0] * SimTK_RADIAN_TO_DEGREE << ", " << range[1] * SimTK_RADIAN_TO_DEGREE << ")" << endl;
                else
                    aStream << " ranges 1 " << coord.getName() << " (" << range[0] << ", " << range[1] << ")" << endl;
            } else {
                aStream << " ranges 1 " 
                    << mvp->getConnector<Coordinate>("coordinate").getConnecteeName()
                    << " (0.0, 1.0)" << endl;
            }
        } else if (pt.getConcreteClassName()==("MovingPathPoint")) {
            MovingPathPoint* mpp = (MovingPathPoint*)(&pt);
            const Vec3& attachment = mpp->get_location();
            if (mpp->hasXCoordinate()) {
                aStream << "f" << addMuscleFunction(&mpp->get_x_location(), mpp->getXCoordinate().getMotionType(), Coordinate::Translational) << "(" << mpp->getXCoordinate().getName() << ") ";
            } else {
                aStream << attachment[0] << " ";
            }
            if (mpp->hasYCoordinate()) {
                aStream << "f" << addMuscleFunction(&mpp->get_y_location(), mpp->getYCoordinate().getMotionType(), Coordinate::Translational) << "(" << mpp->getYCoordinate().getName() << ") ";
            } else {
                aStream << attachment[1] << " ";
            }
            if (mpp->hasZCoordinate()) {
                aStream << "f" << addMuscleFunction(&mpp->get_z_location(), mpp->getZCoordinate().getMotionType(), Coordinate::Translational) << "(" << mpp->getZCoordinate().getName() << ")";
            } else {
                aStream << attachment[2];
            }
            aStream << " segment " << mpp->getBody().getName() << endl;
        } else {
            Vec3& attachment = pt.getLocation();
            aStream << attachment[0] << " " << attachment[1] << " " << attachment[2] << " segment " << pt.getBody().getName() << endl;
        }
    }
    aStream << "endpoints" << endl;

    Array<std::string> groupNames;
    aActuatorSet.getGroupNamesContaining(aMuscle.getName(),groupNames);
    if(groupNames.getSize()) {
        aStream << "begingroups" << endl;
        for(int i=0; i<groupNames.getSize(); i++)
            aStream << " " << groupNames[i];
        aStream << endl << "endgroups" << endl;
    }

    const PathWrapSet& wrapObjects = aMuscle.getGeometryPath().getWrapSet();
    for (int i=0; i<wrapObjects.getSize(); i++)
        aStream << "wrapobject " << wrapObjects.get(i).getWrapObjectName() << " " <<
        (dynamic_cast<WrapEllipsoid*>(&wrapObjects.get(i)) ? (wrapObjects.get(i).getMethodName()+" ") : "") <<
        "range " << wrapObjects.get(i).getStartPoint() << " " << wrapObjects.get(i).getEndPoint() << endl;

    if (dynamic_cast<Schutte1993Muscle_Deprecated*>(&aMuscle))
    {
        Schutte1993Muscle_Deprecated *szh = dynamic_cast<Schutte1993Muscle_Deprecated*>(&aMuscle);

        aStream << "max_force " << szh->getMaxIsometricForce() << endl;
        aStream << "optimal_fiber_length " << szh->getOptimalFiberLength() << endl;
        aStream << "tendon_slack_length " << szh->getTendonSlackLength() << endl;
        aStream << "pennation_angle " << szh->getPennationAngleAtOptimalFiberLength() * SimTK_RADIAN_TO_DEGREE << endl;
        aStream << "max_contraction_velocity " << szh->getMaxContractionVelocity() << endl;
        aStream << "timescale " << szh->getTimeScale() << endl;
        aStream << "muscle_model 4" << endl;

        aStream << "active_force_length_curve f" << addMuscleFunction(&szh->getActiveForceLengthCurve(), Coordinate::Translational, Coordinate::Translational) << endl;

        aStream << "passive_force_length_curve f" << addMuscleFunction(&szh->getPassiveForceLengthCurve(), Coordinate::Translational, Coordinate::Translational) << endl;

        aStream << "tendon_force_length_curve f" << addMuscleFunction(&szh->getTendonForceLengthCurve(), Coordinate::Translational, Coordinate::Translational) << endl;
    }
    else if (dynamic_cast<Thelen2003Muscle_Deprecated*>(&aMuscle))
    {
        Thelen2003Muscle_Deprecated *sdm = dynamic_cast<Thelen2003Muscle_Deprecated*>(&aMuscle);

        aStream << "max_force " << sdm->getMaxIsometricForce() << endl;
        aStream << "optimal_fiber_length " << sdm->getOptimalFiberLength() << endl;
        aStream << "tendon_slack_length " << sdm->getTendonSlackLength() << endl;
        aStream << "pennation_angle " << sdm->getPennationAngleAtOptimalFiberLength() * SimTK_RADIAN_TO_DEGREE << endl;
        aStream << "activation_time_constant " << sdm->getActivationTimeConstant() << endl;
        aStream << "deactivation_time_constant " << sdm->getDeactivationTimeConstant() << endl;
        aStream << "Vmax " << sdm->getVmax() << endl;
        aStream << "Vmax0 " << sdm->getVmax0() << endl;
        aStream << "FmaxTendonStrain " << sdm->getFmaxTendonStrain() << endl;
        aStream << "FmaxMuscleStrain " << sdm->getFmaxMuscleStrain() << endl;
        aStream << "KshapeActive " << sdm->getKshapeActive() << endl;
        aStream << "KshapePassive " << sdm->getKshapePassive() << endl;
        aStream << "damping " << sdm->getDamping() << endl;
        aStream << "Af " << sdm->getAf() << endl;
        aStream << "Flen " << sdm->getFlen() << endl;
        aStream << "muscle_model 9" << endl;
    }
    else if (dynamic_cast<Delp1990Muscle_Deprecated*>(&aMuscle))
    {
        Delp1990Muscle_Deprecated *szh = dynamic_cast<Delp1990Muscle_Deprecated*>(&aMuscle);

        aStream << "max_force " << szh->getMaxIsometricForce() << endl;
        aStream << "optimal_fiber_length " << szh->getOptimalFiberLength() << endl;
        aStream << "tendon_slack_length " << szh->getTendonSlackLength() << endl;
        aStream << "pennation_angle " << szh->getPennationAngleAtOptimalFiberLength() * SimTK_RADIAN_TO_DEGREE << endl;
        aStream << "max_contraction_velocity " << szh->getMaxContractionVelocity() << endl;
        aStream << "timescale " << szh->getTimeScale() << endl;
        aStream << "muscle_model 2" << endl;

        if (szh->getActiveForceLengthCurve())
            aStream << "active_force_length_curve f" << addMuscleFunction(szh->getActiveForceLengthCurve(), Coordinate::Translational, Coordinate::Translational) << endl;

        if (szh->getPassiveForceLengthCurve())
            aStream << "passive_force_length_curve f" << addMuscleFunction(szh->getPassiveForceLengthCurve(), Coordinate::Translational, Coordinate::Translational) << endl;

        if (szh->getTendonForceLengthCurve())
            aStream << "tendon_force_length_curve f" << addMuscleFunction(szh->getTendonForceLengthCurve(), Coordinate::Translational, Coordinate::Translational) << endl;

        if (szh->getForceVelocityCurve())
            aStream << "force_velocity_curve f" << addMuscleFunction(szh->getForceVelocityCurve(), Coordinate::Translational, Coordinate::Translational) << endl;
    }

    aStream << "endmuscle" << endl << endl;
    return true;
}