text:
var db = require('../config');
var bcrypt = require('bcrypt-nodejs');
var Promise = require('bluebird');
var User = require('./user');

var Artist = db.Model.extend({
    tableName: 'artists',

    initialize: function() {
        this.on('creating', function() {
            var model = this;
            var promiseHash = Promise.promisify(bcrypt.hash);
            return promiseHash(model.get('password'), null,null)
                .then(function(hash) {
                    model.set('password', hash);
                });
        });
    },
    users: function() {
        return this.belongsToMany(User); // belongsToMany automatically returns a Collection, so not redq to make it
    }

});

module.exports = Artist;


text:
<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>
<channel>
	<title>Comments on: Gameboy Timing and Timers</title>
	<atom:link href="http://codeslinger.co.uk/pages/blog/wordpress/?feed=rss2&p=4" rel="self" type="application/rss+xml" />
	<link>http://codeslinger.co.uk/pages/blog/wordpress/?p=4</link>
	<description>The art of emulator programming</description>
	<pubDate>Thu, 21 Jul 2011 18:52:06 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
		<item>
		<title>By: pbs kids games</title>
		<link>http://codeslinger.co.uk/pages/blog/wordpress/?p=4#comment-122</link>
		<dc:creator>pbs kids games</dc:creator>
		<pubDate>Tue, 15 Jun 2010 11:09:31 +0000</pubDate>
		<guid isPermaLink="false">http://codeslinger.co.uk/pages/blog/wordpress/?p=4#comment-122</guid>
		<description>I found your website in Google few moments ago, and luckily, this is it I was looking for the last weeks, thanks</description>
		<content:encoded><![CDATA[
I found your website in Google few moments ago, and luckily, this is it I was looking for the last weeks, thanks

]]></content:encoded>
	</item>
</channel>
</rss>

redpajama_set_name: RedPajamaGithub


text:
package org.mamute.infra;

import javax.inject.Inject;

import org.mamute.dao.FlaggableDAO;
import org.mamute.dao.InformationDAO;
import org.mamute.model.LoggedUser;

import br.com.caelum.vraptor.Result;

public class MenuInfo {

	@Inject private Result result;
	@Inject private LoggedUser loggedUser;
	@Inject private FlaggableDAO flaggables;
	@Inject private InformationDAO informations;

	public void include() {
		result.include("currentUser", loggedUser);
		if (loggedUser.canModerate()) {
			Long pendingCount = informations.pendingCount();
			int flaggedCount = flaggables.flaggedButVisibleCount();
			if (loggedUser.isModerator()) {
				result.include("pendingForModeratorCount", pendingCount + flaggedCount);
			} else {
				result.include("pendingForModeratorCount", pendingCount);
			}
		}
	}

}


text:
//===-- Program.cpp - Implement OS Program Concept --------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file implements the operating system Program concept.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Program.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Config/llvm-config.h"
#include <system_error>
using namespace llvm;
using namespace sys;

//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only TRULY operating system
//===          independent code.
//===----------------------------------------------------------------------===//

static bool Execute(ProcessInfo &PI, StringRef Program,
                    ArrayRef<StringRef> Args, Optional<ArrayRef<StringRef>> Env,
                    ArrayRef<Optional<StringRef>> Redirects,
                    unsigned MemoryLimit, std::string *ErrMsg);

int sys::ExecuteAndWait(StringRef Program, ArrayRef<StringRef> Args,
                        Optional<ArrayRef<StringRef>> Env,
                        ArrayRef<Optional<StringRef>> Redirects,
                        unsigned SecondsToWait, unsigned MemoryLimit,
                        std::string *ErrMsg, bool *ExecutionFailed) {
  assert(Redirects.empty() || Redirects.size() == 3);
  ProcessInfo PI;
  if (Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg)) {
    if (ExecutionFailed)
      *ExecutionFailed = false;
    ProcessInfo Result = Wait(
        PI, SecondsToWait, /*WaitUntilTerminates=*/SecondsToWait == 0, ErrMsg);
    return Result.ReturnCode;
  }

  if (ExecutionFailed)
    *ExecutionFailed = true;

  return -1;
}

ProcessInfo sys::ExecuteNoWait(StringRef Program, ArrayRef<StringRef> Args,
                               Optional<ArrayRef<StringRef>> Env,
                               ArrayRef<Optional<StringRef>> Redirects,
                               unsigned MemoryLimit, std::string *ErrMsg,
                               bool *ExecutionFailed) {
  assert(Redirects.empty() || Redirects.size() == 3);
  ProcessInfo PI;
  if (ExecutionFailed)
    *ExecutionFailed = false;
  if (!Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg))
    if (ExecutionFailed)
      *ExecutionFailed = true;

  return PI;
}

bool sys::commandLineFitsWithinSystemLimits(StringRef Program,
                                            ArrayRef<const char *> Args) {
  SmallVector<StringRef, 8> StringRefArgs;
  StringRefArgs.reserve(Args.size());
  for (const char *A : Args)
    StringRefArgs.emplace_back(A);
  return commandLineFitsWithinSystemLimits(Program, StringRefArgs);
}

// Include the platform-specific parts of this class.
#ifdef LLVM_ON_UNIX
#include "Unix/Program.inc"
#endif
#ifdef _WIN32
#include "Windows/Program.inc"
#endif


text:
import random
import hashlib
import bs4
import logging
import requests
import six
import enum
import abc
from coolcantonese.exceptions import TranslationException
from coolcantonese.phonetic import NotationMarker

logger = logging.getLogger(__name__)

class InputLanguage(enum.Enum):
    Mandarin = "Mandarin"
    English = "English"
    AutoDetect = "AutoDetect"

@six.python_2_unicode_compatible
class TranslateResult(object):

    """docstring for TranslateResult"""

    def __init__(self, words="", pronounce_list=None):
        super(TranslateResult, self).__init__()
        self.words = words
        self.pronounce_list = pronounce_list
        if self.pronounce_list is None:
            self.pronounce_list = []
        self.has_symbols = False

    def pretty(self):
        if not self.has_symbols:
            return self.words
        return self.words + "\n\n" + self.get_words_with_pronounces()

    def get_words_with_pronounces(self):
        words = self.words
        # logger.debug("words: %s", words)
        result = ""
        for i, w in enumerate(words):
            result += w
            pronounce = self.pronounce_list[i]
            if pronounce:
                result += "(" + pronounce + ")"
        return result

    def add(self, word, pronounce):
        # logger.debug("word:%, pronounce: %s", word, pronounce)
        self.words += word
        self.pronounce_list.append(pronounce)
        if pronounce:
            self.has_symbols = True

    def get_filename(self, ext=".mp3"):
        filename = ""
        for pronounce in self.pronounce_list:
            if pronounce:
                filename += pronounce
        if "" == filename:
            return None
        filename += ext
        return filename

    def __str__(self):
        return self.pretty()

@six.add_metaclass(abc.ABCMeta)
class Translator():

    """提供普通话到粤语的翻译接口"""

    def __init__(self):
        super(Translator, self).__init__()

    @abc.abstractmethod
    def get_translation(self, text, input_language):
        pass

class L2ChinaTranslator(Translator):

    """通过调用l2china的接口实现翻译功能"""

    def __init__(self):
        super(L2ChinaTranslator, self).__init__()

    def _paser_response(self, resp_text):
        if None:
            return None
        soup = bs4.BeautifulSoup(resp_text, "lxml")
        texts = soup.select("div.generated_text")
        if texts and len(texts) > 0:
            result = TranslateResult()
            span_list = texts[0].select("span")
            for span in span_list:
                word = span.text
                pronounce = span["title"]
                if "null" == pronounce:
                    pronounce = None
                result.add(word, pronounce)
            return result
        raise TranslationException("暂无翻译结果")

    def get_translation(self, text, input_language):
        traslate_url = "http://www.l2china.com/yueyu/"
        text_len_limit = 100

        if isinstance(text, six.text_type):
            # unicode text
            txt_len = len(text)
            utf8_txt = text.encode('utf-8')
        else:
            txt_len = len(text.decode('utf-8'))
            utf8_txt = text
        if txt_len > text_len_limit:
            raise TranslationException(
                "需要翻译的文本超过" + str(text_len_limit) + "个字符")
        params = {"srctxt": utf8_txt, "RadioGroup1": "tocan"}
        resp = requests.get(traslate_url, params=params)
        resp.encoding = 'utf-8'
        if resp.status_code == 200:
            # logger.debug("reponse text: %s", resp.text)
            result = self._paser_response(resp.text)
            return result
        return None

def utf8(text):
    if isinstance(text, six.text_type):
        utf8_txt = text.encode('utf-8')
    else:
        utf8_txt = text
    return utf8_txt

def md5(text):
    utf8_txt = utf8(text)
    m = hashlib.md5()
    m.update(utf8_txt)
    return m.hexdigest()

class BaiduTranslator(Translator):

    """通过调用百度翻译接口实现翻译功能"""

    def __init__(self, app_id, app_secret, notation_marker):
        super(BaiduTranslator, self).__init__()
        self.app_id = app_id
        self.app_secret = app_secret
        self.notation_marker = notation_marker

    def _paser_response(self, resp_json):
        trans_result = resp_json["trans_result"]
        result_text = ""
        for t in trans_result:
            dst = t["dst"]
            result_text = result_text + "\n" + dst
        result_text = result_text[1:]
        r = self.notation_marker.get_noted_chars(result_text)
        logger.debug(r.noted_chars)
        result = TranslateResult()
        result.words = r.in_str
        result.pronounce_list = r.noted_chars
        result.has_symbols = True
        return result

# 字段名 类型  必填参数    描述  备注
# q   TEXT    Y   请求翻译query   UTF-8编码
# from    TEXT    Y   翻译源语言   语言列表(可设置为auto)
# to  TEXT    Y   译文语言    语言列表(不可设置为auto)
# appid   INT Y   APP ID  可在管理控制台查看
# salt    INT Y   随机数
# sign    TEXT    Y   签名  appid+q+salt+密钥 的MD5值
    def get_translation(self, text, input_language):
        api_url = "http://api.fanyi.baidu.com/api/trans/vip/translate"
        salt = str(random.randint(0, 1000000000000000))
        if isinstance(text, six.text_type):
            utf8_txt = text.encode('utf-8')
        else:
            utf8_txt = text
        sign = md5(self.app_id + text + salt + self.app_secret)
        from_language = "auto"
        if input_language is InputLanguage.Mandarin:
            from_language = "zh"
        elif input_language is InputLanguage.English:
            from_language = "en"

        params = {
            "from": from_language,
            "to": "yue",
            "appid": self.app_id,
            "q": utf8_txt,
            "salt": salt,
            "sign": sign,
        }

        resp = requests.get(api_url, params=params)
        resp.encoding = 'utf-8'
        if resp.status_code == 200:
            logger.debug("reponse json: %s", resp.json())
            result = self._paser_response(resp.json())
            return result
        return None

class SmartTranslator(object):

    """提供普通话到粤语的翻译接口"""

    def __init__(self, cfg):
        super(SmartTranslator, self).__init__()
        self.translators = []
        if cfg.use_baidu_translator:
            notation_marker = NotationMarker(cfg.phonetic_data_path)
            self.translators.append(
                BaiduTranslator(
                    cfg.baidu_app_id, cfg.baidu_app_secret, notation_marker
                )
            )
        if cfg.use_l2china_translator:
            self.translators.append(L2ChinaTranslator())

    def get_translation(self, text, input_language=InputLanguage.AutoDetect):
        last_exception = None
        for translator in self.translators:
            try:
                result = translator.get_translation(text, input_language)
                if result:
                    return result
            except Exception as e:
                last_exception = e
        if last_exception:
            raise last_exception
        return None


text:
Automatizar con grunt y docco (o algún otro sistema) la generación de documentación de la librería que se cree. Previamente, por supuesto, habrá que documentar tal librería.

# Solucion

Para python hay varias herramientas de documentación y muchas son muy extendidas.
Una de ellas se utiliza en django donde su uso es casi obligatorio: sphinx.

Para instalar sphinx se puede realizar desde pip como cualquier otro paqueta y dispone de su propio lenguaje de etiquetas como ocurre con otras conocidas herramientas como javadoc y doxygen, sin embargo esta herramienta tiene un lenguaje mucho más potente permitiendo el uso de tablas y estilos.

En realidad se utiliza [autodoc](http://sphinx-doc.org/ext/autodoc.html) una extensión de sphinx que sería lo equivalente a javadoc, ya que sphinx en realidad es mucho mas potente y te permite generar contenido y/o secciones adicionales.

Puedes ver la documentación generada de mi proyecto [aquí](http://francisconavarro.nom.es/cloudcomputing/doc/)

Y ver los archivos de en el repositorio:

[Configuración](https://github.com/fnavarrogonzalez/RankingEmpresas/tree/master/rankingempresas/source)

[Generados](https://github.com/fnavarrogonzalez/RankingEmpresas/tree/master/rankingempresas/build)


text:
module RRImm
  class Cache

    attr_accessor :name
    attr_accessor :path

    REMOVE_PATTERNS = [
        /^.*:\/\/\/?/,
        /^(http|ftp|file)s?___/,
        /_+$/,
    ]

    INVALID_PATTERNS = [
        /[^\w]/,
    ]

    DEFAULT_TIMESTAMP = 1

    def initialize(name)
       @name = name
       @path = name
    end

    def path(arg=nil)
      if arg
        @path = arg
      end
      @path
    end

    def cache_file(feed)
      filename = sanitize(feed.uri)
      File.join(path, filename)
    end

    def read(feed)
      file_path = cache_file(feed)

      return DEFAULT_TIMESTAMP unless File.exists?(file_path)
      timestamp = File.read(file_path)
      timestamp.to_i
    end

    def save(feed, timestamp, force=true)
      ensure_cache_dir!
      file_path = cache_file(feed)
      File.write(file_path, timestamp) if (force or timestamp != read(feed))
    end

    private
    def sanitize(name)
      cleaned_name = INVALID_PATTERNS.inject(name) do |memo,pattern|
        memo.gsub(pattern, '_')
      end
      REMOVE_PATTERNS.inject(cleaned_name) do |memo,pattern|
        memo.gsub(pattern, '')
      end
    end

    def ensure_cache_dir!
      @cache_dir_exists ||= Dir.exists?(path) || Dir.mkdir(path)
    end
  end
end


text:
import numpy
import math
from itertools import combinations_with_replacement, chain, groupby, compress
from collections import Counter
import molecule
import constants
import UCONGA_generate as UCONGA
matplotlib_available = False
cluster_available = False
try:
    import matplotlib.pyplot as plt
    from matplotlib.ticker import FixedLocator
    matplotlib_available = True
except ImportError:
    pass
try:
    import scipy.cluster
    cluster_available = True
except ImportError:
    pass
import warnings
from os import path
# Molecule preparation functions

def canonicalise(mol):
    '''
    Canonicalise a molecule with respect to nuclear permutational symmetry
    For each symmetric group, choose the equivalent position that UCONGA_generate
        would generate
    Accepts: a molecule object
    '''
    rb = UCONGA.find_rotatable_bonds(mol)
    centralness = [sum(i) for i in mol.distances]
    classes = mol.get_morgan_equivalencies()
    # Normalise the coords for the reference w. r. t. the symmetry operations:
    for each_bond in rb:
        if centralness[each_bond[0]] > centralness[each_bond[-1]]:
            each_bond = each_bond[::-1]
        if UCONGA.is_symmetrical_rotor(each_bond, mol, classes):
            sym_degree = float(len(mol.atoms[each_bond[2]].search_away_from(each_bond[1])))
            increment = 2 * math.pi / sym_degree
            each_torsion = mol.get_torsion(*each_bond)
            while each_torsion > increment:
                each_torsion -= increment
            while each_torsion < 0:
                each_torsion += increment
            mol.set_torsion(*([i for i in each_bond] + [each_torsion]))
    # Group bonds by siblings - this is inefficient but not the limiting factor performance-wise
    new_dict = {}
    partial_symmetry_groups = []
    for each_id, each_bond in enumerate(rb):
        if centralness[each_bond[0]] > centralness[each_bond[-1]]:
            each_bond = each_bond[::-1]
        elder_bond_ids = []
        for i in UCONGA.find_older_sibling_ids(each_bond, each_id, mol, classes, new_dict):
            elder_bond_ids.append(int(i))
        app = [each_bond]
        for i in elder_bond_ids:
            i_bond = rb[i]
            if centralness[i_bond[0]] > centralness[i_bond[-1]]:
                i_bond = i_bond[::-1]
            app.append(i_bond)
        partial_symmetry_groups.append(app)
    partial_symmetry_groups.sort(key=len)
    # Remove the incomplete groups
    working_idx = 0
    while working_idx < len(partial_symmetry_groups) - 1:
        to_test = []
        for i in partial_symmetry_groups[working_idx + 1:]:
            if partial_symmetry_groups[working_idx][0] in i:
                del partial_symmetry_groups[working_idx]
                break
        else:
            working_idx += 1
    for each_whole_group in partial_symmetry_groups:
        ab = [int(math.degrees(mol.get_torsion(*i))) for i in each_whole_group]
        for idx, i in enumerate(ab):
            if i < 0:
                ab[idx] = i + 360
        ab.sort()
        for each_bond, each_torsion in zip(each_whole_group, ab):
            repacked = [i for i in each_bond] + [math.radians(each_torsion)]
            mol.set_torsion(*repacked)

def calculate_I_tensor(coords, weights):
    '''
    Calculate the inertia tensor of a molecule

    Accepts: a coordinate matrix
             a list of atomic weights

    Returns: the inertia tensor
    '''
    x = coords[:, 0]
    y = coords[:, 1]
    z = coords[:, 2]
    I_xx = numpy.sum(weights * (y * y + z * z))
    I_xy = numpy.sum(weights * x * y) * -1
    I_xz = numpy.sum(weights * x * z) * -1
    I_yy = numpy.sum(weights * (x * x + z * z))
    I_yz = numpy.sum(weights * y * z) * -1
    I_zz = numpy.sum(weights * (x * x + y * y))
    return numpy.array([[I_xx, I_xy, I_xz],
                        [I_xy, I_yy, I_yz],
                        [I_xz, I_yz, I_zz]])

def align_inertial(mol):
    '''
    Aligns a molecule so that its axes of inertia are aligned to the coordinate axes
    The primary axis (highest moment) will be aligned to the z-axis,
    while the tertiary (lowest moment) axis will be aligned to the x-axis

    Accepts: a molecule

    Returns: nothing, it modifies the molecule in-place
    '''
    c_weights = numpy.array([[constants.periodic_table[constants.periodic_list[i.num]]['mass']]
                             for i in mol.atoms])
    r_weights = c_weights.T[0]
    c_coords = mol.coord_matrix()
    # centre on the COM
    weighted_coords = c_weights * c_coords
    all_weight = sum(c_weights)
    com = weighted_coords.sum(axis=0) / all_weight
    c_coords -= com
    intertia_mat = calculate_I_tensor(c_coords, r_weights)
    moments, axes = numpy.linalg.eig(intertia_mat)
    tmp = [(j, k) for j, k in zip(moments, axes)]
    sorted_axes = numpy.array([i[1] for i in sorted(tmp)])
    c_new_coords = sorted_axes.T.dot(c_coords.T).T
    for a, c in zip(mol.atoms, c_new_coords):
        a.coords = c

def find_bbox(mol):
    """
    Find the bounding box dimensions along the inertial axes

    Accepts: a molecule

    Returns: The three bouding-box side lengths, from lowest to highest moment
             of inertia, as a numpy array
    """
    align_inertial(mol)
    # Find the eliptical radii along the axes of inertia
    x = [i.coords[0] for i in mol.atoms]
    r_x = max(x) - min(x)
    y = [i.coords[1] for i in mol.atoms]
    r_y = max(y) - min(y)
    z = [i.coords[2] for i in mol.atoms]
    r_z = max(z) - min(z)
    return numpy.array([r_x, r_y, r_z])

def prepare_angles(important_torsions, mols, allow_inversion):
    '''
    Read torsional data from a lost of molecules at once, in preparation for
    torsion-based clustering
    Accepts:
        A list of lists of atom ids for torsions of interest
        A list of molecules
        Whether or not enantiomers should be trated as identical
    Returns: A list of lists of torsion values for each molecule, in radians
    '''
    tc_angles = [[mol.get_torsion(*torsion) for torsion in important_torsions]
                 for mol in mols]
    if allow_inversion:
        new_angles = []
        for each_mol in tc_angles:
            if each_mol[0] < 0:
                new_angles.append([i * -1 for i in each_mol])
            else:
                new_angles.append(each_mol)
        tc_angles = new_angles
    return tc_angles
# Clustering-related functions

def ch_cluster(data, method):
    '''
    Perform clustering on an array of data and
    calculate the Calinski-Harabasz Criterion for various k
    See Calinski and Harabasz., Commun. Stat., 1974, p 1

    Accepts: an array of data, with individual data points as the rows
            a function which takes that data and a number of clusters,
            and returns a list of each data points' cluster ids, the cluster centers,
            the total distortion, and a list of the distance from each point to its nearest center

    Returns: a list of tuples containg: the criterion
                                        a list of each conformer's cluster id
                                        a list of the distance from each conformer to its cluster center
    Note that the list starts for two clusters, as the criterion cannot be calulated for one
    '''

    all_data = []
    num_points = len(data)
    std_devs = numpy.std(data, axis=0)
    # Remove any columns with a standard deviation of 0, which cannot be whitened
    data_to_use = numpy.array([i for i in compress(data.transpose(), std_devs)]).transpose()
    mean = numpy.mean(data_to_use, axis=0)
    if num_points > 15:
        num_points = int(2 * math.sqrt(num_points))
    for num_clusters in range(2, num_points):
        with warnings.catch_warnings(record=True) as warnings_log:
            mapping, codebook, total_distortion, point_distortions = method(data_to_use, num_clusters)
        if total_distortion == 0:
            warnings.warn('Clustering with %d clusters has too many degrees of freedom. Are some conformers degenerate?' % num_clusters, RuntimeWarning)
        else:
            counts = Counter(mapping)
            ssb = sum([counts[idx] * (numpy.linalg.norm(mean - i) ** 2)
                       for idx, i in enumerate(codebook)])
            ch_criterion = ((num_points - num_clusters) * ssb) / ((num_clusters - 1) * total_distortion)
            all_data.append([ch_criterion, mapping, point_distortions])
    return all_data

def cluster_kmeans(data, k):
    '''
    Performs k-means clustering on a numpy array of data.

    Accepts: an array of data, with individual data points as the rows
             The number of clusters to make

    Returns: a list of each data points' cluster ids
             a list of the cluster centers,
             the total distortion,
             a list of the distances from each point to its nearest center
    '''
    whitened_data = scipy.cluster.vq.whiten(data)
    codebook, total_distortion = scipy.cluster.vq.kmeans(whitened_data, k, iter=50)
    mapping, point_distortions = scipy.cluster.vq.vq(whitened_data, codebook)
    return mapping, codebook, total_distortion, point_distortions

def cluster_hierarchy(data, k):
    '''
    Performs hierarchical clustering on a numpy array of data

    Accepts: an array of data, with individual data points as the rows
             The number of clusters to make

    Returns: a list of each data points' cluster ids
             a list of the cluster centers,
             the total distortion,
             a list of the distances from each point to its nearest center
    '''
    distmat = scipy.spatial.distance.pdist(data)
    linkmat = scipy.cluster.hierarchy.linkage(distmat, method='average')
    mapping = scipy.cluster.hierarchy.fcluster(linkmat, k, criterion='maxclust')
    mapped_points = [(i, data[i]) for i in mapping]
    mapped_points.sort(key=lambda x: x[0])
    clusters = [[j[1] for j in i[1]] for i in groupby(mapped_points, key=lambda x: x[0])]
    codebook = numpy.array([numpy.array(i).mean(axis=0) for i in clusters])
    total_distortion = sum([numpy.linalg.norm(i[1] - codebook[i[0] - 1])
                            for i in mapped_points])
    return mapping, codebook, total_distortion, point_distortions

def choose_best_clustering(clustering):
    '''
    Choose the best cluster size according to the *first derivative* of the
    Calinski-Harabasz criterion
    Accecpts: a list of tuples of cluster details where the first item is the
                        Calinski-Harabasz metric, the second item is the codebook,
                        and the third item is the list of distances from points to
                        the closest cluster centers
    Returns:
            The codebook and list of distances for the best clustering
    '''
    ch_criteria = [i[0] for i in clustering]
    if len(ch_criteria) == 1:
        best_id = 0
    elif len(ch_criteria) == 2:
        best_id = ch_criteria.index(max(ch_criteria))
    else:
        choose_by = ([2 * (ch_criteria[0] - ch_criteria[1])] +
                     [2 * j - i - k for i, j, k in zip(ch_criteria[:-2], ch_criteria[1:-1], ch_criteria[2:])]
                     + [2 * (ch_criteria[-1] - ch_criteria[-2])])
        best_id = choose_by.index(max(choose_by))
    return clustering[best_id][1:]

def reorder(lst, codebook):
    '''
    Reorders the items in a list according to a codebook
    Accepts:
        A list of items to reorder
        A list of the indices they should be in
    Returns
        A new list
    '''
    tmp = [i for i in zip(codebook, lst)]
    tmp.sort()
    return [i[1] for i in tmp]
#### RMSD-related functions

def calc_rmsd(coords_1, coords_2):
    '''
    Calculates rmsd between two lists of coordinates
    No alignment is performed
    Accepts: Two sets of coordinates as numpy arrays
    Returns: The RMSD
    '''
    n = len(coords_1)
    assert n == len(coords_2)
    return math.sqrt(sum([numpy.linalg.norm(i - j) ** 2
                          for i, j in zip(coords_1, coords_2)]) / float(n))

def align(coords_1, coords_2, allow_inversion=True):
    '''
    Calculates a transformation matrix to minimise the rmsd between two sets of coordinates
    The rmsd is not calculated
    Accepts:
        Two sets of coordinates as numpy arrays
        Whether or not inversion is allowed in the transformation
    Returns:
        A transformation matrix as a numpy array

    The transformation is a combination of rotations, reflections, and inversion
    This uses the Schonemann soltion to the orthogonal procrustes problem if inversion is allowed
    see Schonemann, Psychometrika 1966, p.1
    If inversion is not allowed, the Kabsch algorithm is used.
    See Kabsch, Acta Crystallogr. Sect. A 1976, p. 922 and
    Kabsch, Acta Crystallogr. Sect. A 1978, p. 827.
    '''
    M = coords_1.transpose().dot(coords_2)
    U, s, V_H = numpy.linalg.svd(M)
    if allow_inversion:
        return U.dot(V_H)
    else:
        V = numpy.transpose(V_H)
        U_H = numpy.transpose(U)
        d = [1.0 for i in U_H]
        d[-1] = numpy.linalg.slogdet(V.dot(U_H))[0]
        D = numpy.diag(d)
        return U.dot(D.dot(V_H))

def calc_min_rmsd(coords_1, coords_2, allow_inversion=True):
    '''
    Aligns the second set of coordinates to the first and then calculates the rmsd
    Accepts:
        Two sets of coordinates as numpy arrays
        Whether or not inversion is allowed in the transformation
    Returns:
        The RMSD
    '''
    alignment = align(coords_1, coords_2, allow_inversion)
    aligned_1 = coords_1.dot(alignment)
    return calc_rmsd(aligned_1, coords_2)

def all_the_rmsds(molecules, allow_inversion=True):
    '''
    Calculates all the rmsds in a collection of molecules with pariwise alignment
    Accepts:
        A list of molecule objects
        Whether or not inversion is allowed during the alignment
    Returns:
        A matrix of all the pairwise RMSDS
    '''
    l = len(molecules)
    rmsds = [[0 for j in range(l)] for i in range(l)]
    for i in molecules:
        i.center()
    coords = [j.coord_matrix() for j in molecules]
    for i, j in combinations_with_replacement(range(l), 2):
        r = calc_min_rmsd(coords[i], coords[j], allow_inversion)
        rmsds[i][j] = r
        rmsds[j][i] = r
    return rmsds
###### Graphing functions

def bbox_scatter(points, labs, ax=None):
    '''
    Makes a scatter plot of the bounding boxes colored by clustering
    Accepts:
    A list of data points
    A list of the cluster ids of each data point
    An optional matplotlib axis
    '''

    ax = ax if ax is not None else plt.gca()
    ax.set_title('Scatter plot of bounding-box clustering', size='x-large')
    ax.yaxis.set_ticks_position('left')
    ax.xaxis.set_ticks_position('bottom')
    colors = plt.cm.Set1(numpy.linspace(0, 1, max(labs) + 1 - min(labs)))
    percentiles = numpy.percentile(points, [75, 25], axis=0)
    iqrs = percentiles[0] - percentiles[1]
    labels = ('Tertiary axis of inertia ($\AA$)',
              'Secondary axis of inertia ($\AA$)',
              'Primary axis of inertia ($\AA$)')
    tmp = [(i, idx) for idx, i in enumerate(iqrs)]
    tmp.sort()
    x_idx = tmp[2][1]
    y_idx = tmp[1][1]
    ax.set_ylabel(labels[y_idx], size='x-large')
    ax.set_xlabel(labels[x_idx], size='x-large')
    c_array = [colors[i] for i in labs]
    ax.scatter(points[:, x_idx], points[:, y_idx], s=50, c=c_array, marker='+')
    plt.show()

def parallel_coordinates(data, torsion_labels, categories, allow_inversion, ax=None):
    '''
    Makes a parallel coordinates plot of the torsion angles colored by clustering
    Attempts to make all cluster centers as visually close to each other as possible,
    and all data points as visually close to their center as possible
    Accepts:
    A list of data points
    A list of the torsion labels as strings
    A list of the cluster ids of each data point
    Whether or not enantiomers should be treated as identical
    An optional matplotlib axis
    '''
    ax = ax if ax is not None else plt.gca()
    ax.set_title('Parallel coordinates plot of torsional clustering', size='x-large')
    colors = plt.cm.Set1(numpy.linspace(0, 1, max(categories) + 1 - min(categories)))
    ax.yaxis.set_ticks_position('left')
    ax.xaxis.set_ticks_position('bottom')
    ax.set_ylabel('Torsion angle value ($^\circ$)', size='x-large')
    ax.set_xlabel('Torsion label', size='x-large')
    label_positions = range(-360, 450, 90)
    ax.yaxis.set_major_locator(FixedLocator([math.radians(i) for i in label_positions]))
    ax.yaxis.set_ticklabels([str(i) for i in label_positions], size='large')
    x_coords = [0.3 * i for i in range(len(torsion_labels))]
    ax.xaxis.set_major_locator(FixedLocator(x_coords))
    ax.xaxis.set_ticklabels(torsion_labels, size='large')
    # The tricky thing about plotting angles on a flat graph is getting the wrapping right - is 0 or 360 more communicative?
    # To do this, find the centers of the clusters, wrap them to be as close to each other as possible,
    # and wrap the conformers in each cluster to be as close to its center as possible. That creates good wrapping
    for each_mol in data:
        if allow_inversion and each_mol[0] < 0:
            for idx, i in enumerate(each_mol):
                each_mol[idx] = i * -1
    all_centers = []
    clusters = [[j for j, k in zip(data, categories) if k == i]
                for i in range(max(categories) + 1)]
    for each_cluster in clusters:
        # To average angles, they need to be converted to sines and cosines:
        tmp = []
        for mol in each_cluster:
            transformed_angles = [(math.sin(angle), math.cos(angle)) for angle in mol]
            tmp.append([i for i in chain(*transformed_angles)])
        cart_conformers = numpy.array(tmp)
        average = numpy.mean(cart_conformers, axis=0)
        center = [math.atan2(s, c) for s, c in zip(average[::2], average[1::2])]
        all_centers.append(center)
    for each_center, each_cluster, each_color in zip(all_centers, clusters, colors):
        for idx, i in enumerate(each_center):
            j = all_centers[0][idx]

            if math.pi < j - i:
                each_center[idx] = i + 2 * math.pi
            elif math.pi < i - j:
                each_center[idx] = i - 2 * math.pi
        for each_conformers in each_cluster:
            for idx, i in enumerate(each_conformers):
                j = each_center[idx]
                if math.pi < j - i:
                    each_conformers[idx] = i + 2 * math.pi
                if math.pi < i - j:
                    each_conformers[idx] = i - 2 * math.pi
            ax.plot(x_coords, each_conformers, color=each_color)
    curr_ylim = [int(math.degrees(i)) for i in ax.get_ylim()]
    new_ylim = (90 * (curr_ylim[0] / 90) - 5, 5 + (90 * ((curr_ylim[1] + 89) / 90)))
    ax.set_ylim([math.radians(i) for i in new_ylim])
    plt.tight_layout()
    plt.show()

def greyscale_visualisation(matrix, max_weight=None, ax=None, filename=None):
    """
    Visulaise a matrix (all entries positive real) as a greyscale square diagram
    Light = small number, dark = large number
    Accepts:
        A matrix to visualise
        An optional value to set to black
        An optional matplotlib axis object
        An optional filename to save to instead of showing
    If a maximum weight (which will correspond to black) is not provided,
    2**ceiling(log2[max]) is used, where max is the largest entry in the matrix
    """
    ax = ax if ax is not None else plt.gca()
    ax.set_title('Greyscale visualisation of the RMSD matrix', size='x-large')
    if not max_weight:
        max_weight = 2 ** numpy.ceil(numpy.log(numpy.abs(matrix).max()) / numpy.log(2))
    i = ax.matshow(matrix, vmin=0, vmax=max_weight, cmap='Greys')
    ax.xaxis.set_major_locator(plt.NullLocator())
    ax.yaxis.set_major_locator(plt.NullLocator())
    ax.set_xlabel('Conformer Number', size='x-large')
    ax.set_ylabel('Conformer Number', size='x-large')
    ax.text(1.2, 0.5, 'RMSD similarity', size='x-large', transform=ax.transAxes,
            rotation='vertical', verticalalignment='center')
    plt.colorbar(i)
    if not filename:
        plt.show()
    else:
        plt.savefig(filename)

if __name__ == '__main__':
    import argparse
    import csv
    from sys import stdout
    from glob import glob
    description = '''
    UCONGA: Universal CONformer Generation and Analysis
    ---------------------------------------------------
    A conformer diversity analysis tool that doesn't assume you're trying
    to dock a drug-like molecule to a protein.
    ----------------------------------------------------------------------
    Nathaniel Gunby, Dr. Deborah Crittenden, Dr. Sarah Masters
    Department of Chemistry
    University of Canterbury
    Christchurch
    New Zealand
    '''
    kt_help = '''Number of clusters for torsion-based clustering.
        If omitted or negative, k will be chosen using the Calinski-Harabasz Criterion
        If 0, torsion-based clustering will not be performed'''
    kb_help = '''Number of clusters for bounding-box-based clustering.
                If omitted or negative, k will be chosen using the Calinski-Harabasz Criterion
                If 0, bounding-box-based clustering will not be performed'''
    a_help = 'Run automatically (do not make graphs)'
    n_help = 'Do not calculate the rmsd matrix (this gets expensive for large ensembles)'
    o_help = 'File to write the results to. Default: stdout'
    i_help = 'Treat enantiomeric conformers as identical? (Default = No)'
    u_help = 'RMSD cutoff in Angstroms to treat conformers as unique (default = 1)'
    c_help = 'Use hierachical clustering (default = k-means clustering)'
    r_help = ('How to arrange molecules for RMSD visualisation (t = torsion ' +
              'clustering, b = bounding-box clustering, i or unspecified = conformer id)')
    parser = argparse.ArgumentParser(description=description,
                                     formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('-t', '--k_torsional', help=kt_help, type=int, default=-1)
    parser.add_argument('-b', '--k_bounding', help=kb_help, type=int, default=-1)
    parser.add_argument('-o', '--output_name', help=o_help, default=stdout,
                        type=argparse.FileType('wb'))
    parser.add_argument('-r', '--rmsd_arrange', help=r_help, default='i')
    parser.add_argument('-n', '--no_rmsd', help=n_help, action='store_true')
    parser.add_argument('-a', '--automatic', help=a_help, action='store_true')
    parser.add_argument('-i', '--allow_inversion', help=i_help, action='store_true')
    parser.add_argument('-u', '--uniqueness_cutoff', type=float, help=u_help, default=1.0)
    parser.add_argument('-H', '--use_hierachical_clustering', help=c_help,
                        action='store_true')
    parser.add_argument('input_files', help='cml files containing the conformers' +
                                            ' to be analysed', nargs='+')
    # Prepare input
    args = parser.parse_args()
    input_names = args.input_files
    for idx, i in enumerate(input_names):
        if '*' in i:
        # If the shell is dumb (powershell/cmd.exe), glob input files ourselves
            input_names[idx:idx + 1] = glob(i)
    mols = [molecule.from_cml(i) for i in input_names]
    for i in mols:
        canonicalise(i)
    # Clean up the molecule names for pretty-printing
    mol_names = [path.splitext(path.split(i)[1])[0] for i in input_names]

    writer = csv.writer(args.output_name)
    if args.use_hierachical_clustering:
        cluster = cluster_hierarchy
    else:
        cluster = cluster_kmeans
    # Validate input
    if len(set([len(i.atoms) for i in mols])) != 1:
        raise ValueError('Not all molecules to be analysed have the same number ' +
                         'of atoms. Please retry with conformers of only one molecule')
    if args.rmsd_arrange not in ['t', 'b', 'i']:
        raise ValueError('RMSD arrangement must be by [t]orsion clustering, ' +
                         '[b]ounding box clustering, or conformer [i]d')
    if (not cluster_available) and (args.k_torsional or args.k_bounding):
        warnings.warn('Scipy not detected. Will not perform clustering')
    if (len(mol_names) <= 3) and (args.k_torsional or args.k_bounding):
        warnings.warn('Not enough conformers to perform clustering')
    if args.rmsd_arrange and args.no_rmsd:
        warnings.warn('Instructions on how to arrange rmsd will be ignored ' +
                      'because rmsds are not calculated', RuntimeWarning)
    if (args.rmsd_arrange == 't') and ((args.k_torsional == 0) or (not cluster_available)
                                       or (len(mol_names) <= 3)):
        raise ValueError('Cannot arrange conformers by torsion clustering if ' +
                         'torsion clustering is not performed')
    if args.rmsd_arrange == 'b' and args.k_bounding == 0:
        raise ValueError('Cannot arrange conformers by bounding-box clustering' +
                         'if bounding-box clustering is not performed')
    # Do the clustering
    clustering_results = [mol_names]
    clustering_headings = ['Conformer name']
    # Torsional clustering
    if args.k_torsional != 0 and len(mol_names) > 3 and cluster_available:
        backbone, b_t_m = mols[0].copy_without_H()
        important_torsions = [[b_t_m[at] for at in it] for it in backbone.all_torsions()]
        important_angles = prepare_angles(important_torsions, mols, args.allow_inversion)
        tc_angles = numpy.array([[i for i in chain(*[(math.sin(angle), math.cos(angle)) for angle in mol])]
                                 for mol in important_angles])
        if args.k_torsional > 0:
            writer.writerow(['Finding %d torsional clusters' % args.k_torsional])
            t_ordering, tmp1, tmp2, t_distances = cluster(tc_angles, args.k_torsional)
        else:
            writer.writerow(['Finding torsional clusters with Calinski-Harabasz criterion'])
            t_clustering = ch_cluster(tc_angles, cluster)
            # Output the quality of the clustering
            t_ordering, t_distances = choose_best_clustering(t_clustering)
        tc_headings = clustering_headings + ['Torsional cluster id',
                                             'Distance from torsional cluster center']
        tc_headings += ['-'.join([str(j + 1)for j in i]) for i in important_torsions]
        writer.writerow(tc_headings)
        tc_results = clustering_results + ([t_ordering, t_distances])
        for i in range(len(important_torsions)):
            tc_results.append([math.degrees(j[i]) for j in important_angles])
        writer.writerows([i for i in zip(*tc_results)])
    # Bonding-box clustering
    if args.k_bounding != 0 and len(mol_names) > 3 and cluster_available:
        tc_bbox = numpy.array([find_bbox(i) for i in mols])
        if args.k_bounding > 0:
            writer.writerow(['Finding %d bounding-box clusters' % args.k_bounding])
            b_ordering, tmp1, tmp2, b_distances = cluster(tc_bbox, args.k_bounding)
        else:
            writer.writerow(['Finding bounding-box clusters with Calinski-Harabasz Criterion'])
            b_clustering = ch_cluster(tc_bbox, cluster)
            # Output the quality of the clustering
            b_ordering, b_distances = choose_best_clustering(b_clustering)
        b_headings = clustering_headings + (['Bounding-box cluster id',
                                             'Distance from bounding-box cluster center',
                                             'Tertiary axis of inertia',
                                             'Secondary axis of inertia',
                                             'Primary axis of inertia'])
        b_results = clustering_results + [b_ordering, b_distances, tc_bbox[:, 0],
                                          tc_bbox[:, 1], tc_bbox[:, 2]]
        writer.writerow(b_headings)
        writer.writerows([i for i in zip(*b_results)])
    # Calculate the RMSD matrix and perform filtering if desired
    if not args.no_rmsd:
        writer.writerow(['RMSD matrix'])
        if args.rmsd_arrange == 't':
            reorder(mols, t_ordering)
        if args.rmsd_arrange == 'b':
            reorder(mols, b_ordering)
        rmsds = all_the_rmsds(mols, allow_inversion=args.allow_inversion)
        writer.writerow(['Conformers'] + mol_names)
        for i, j in zip(mol_names, rmsds):
            writer.writerow([i] + j)
        # Use the rmsds to list the unique conformers
        writer.writerow(['Unique conformers'])
        accepted_ids = []
        for idx, rmsd_list in enumerate(rmsds):
            maybe_unique = [j for jdx, j in enumerate(rmsd_list[:idx])
                            if jdx in accepted_ids]
            if len(maybe_unique) == 0 or min(maybe_unique) > args.uniqueness_cutoff:
                writer.writerow([mol_names[idx]])
                accepted_ids.append(idx)
    # Visualise things
    if matplotlib_available and not args.automatic:
        if not args.no_rmsd:
            greyscale_visualisation(rmsds)
        if matplotlib_available and args.k_torsional and len(mol_names) > 3:
            parallel_coordinates(important_angles, ['-'.join([str(j + 1)for j in i]) for i in important_torsions], t_ordering, args.allow_inversion)
        if matplotlib_available and args.k_bounding and len(mol_names) > 3:
            bbox_scatter(tc_bbox, b_ordering)


text:
import {Component} from "@angular/core";
import {CheckBoxStatus} from "jigsaw/public_api";

@Component({
    templateUrl: './demo.component.html',
    styleUrls: ['./demo.component.css']
})
export class CheckBoxFullComponent {
    //demo-1
    demo1Checked = CheckBoxStatus.unchecked;
    enableIndeterminate: boolean = false;

    //demo-2
    demo2Checked = CheckBoxStatus.indeterminate;

    //demo-3
    demo3Checked = CheckBoxStatus.checked;
    enabled: boolean;

    // ====================================================================
    // ignore the following lines, they are not important to this demo
    // ====================================================================
    summary: string = '演示了`JigsawCheckBox`的效果';
    description: string = '';
}


text:
layout: page
title: Galloway Entertainment Show
date: 2016-05-24
author: Kevin Oconnor
tags: weekly links, java
status: published
summary: Curabitur finibus purus tortor. Etiam.
banner: images/banner/people.jpg
booking:
  startDate: 10/16/2019
  endDate: 10/21/2019
  ctyhocn: HGRMDHX
  groupCode: GES
published: true
---
In cursus tincidunt ligula, sit amet efficitur augue lobortis dictum. Vivamus sed efficitur metus, et consectetur risus. Etiam suscipit, ex eu volutpat pharetra, orci erat vehicula leo, eu convallis purus nibh placerat magna. Nam luctus maximus lobortis. Duis maximus metus rhoncus nisi vestibulum hendrerit. Mauris id lorem consequat, placerat nulla ac, rutrum est. Duis nulla risus, gravida aliquet nibh nec, faucibus iaculis velit. Praesent vitae venenatis elit. Ut ultricies tortor felis. Aliquam semper tellus a hendrerit interdum. Vestibulum rutrum mattis elit, pellentesque maximus lacus consequat eget.

* Aenean sit amet enim facilisis, egestas justo a, egestas est
* Nunc porta purus quis euismod suscipit
* Curabitur non ipsum et dolor aliquet egestas
* Fusce blandit tortor at tincidunt facilisis.

Suspendisse neque arcu, cursus et arcu vel, lacinia porta dolor. Vestibulum vitae viverra neque. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vel arcu non risus elementum ornare at quis sem. Donec non consectetur mi. Nullam pulvinar fringilla sem. Aliquam diam mi, suscipit at facilisis et, lobortis et dui. Nunc eu tempor tellus. Integer dictum, leo at consequat rutrum, odio ligula ultrices leo, laoreet dignissim risus dui vitae tellus. Nulla facilisi. Vestibulum faucibus iaculis pellentesque. Curabitur ut mi ac sem congue sagittis.
Etiam ac quam ac nisl malesuada ullamcorper eu non velit. Quisque mauris ante, sollicitudin ac bibendum sed, tincidunt non sem. Integer ligula sapien, consectetur hendrerit libero et, varius sollicitudin erat. Duis vehicula dui nec odio blandit bibendum. Ut sollicitudin accumsan purus non vestibulum. Nam quis diam pretium magna volutpat vestibulum. Cras pulvinar sagittis eros, porttitor ultrices risus. Mauris et pellentesque felis.


text:
/// \file   X3DImporter_Geometry3D.cpp
/// \brief  Parsing data from nodes of "Geometry3D" set of X3D.
/// \date   2015-2016
/// \author smal.root@gmail.com

#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER

#include "X3DImporter.hpp"
#include "X3DImporter_Macro.hpp"

// Header files, Assimp.
#include "StandardShapes.h"

namespace Assimp
{

// <Box
// DEF=""       ID
// USE=""       IDREF
// size="2 2 2" SFVec3f [initializeOnly]
// solid="true" SFBool  [initializeOnly]
// />
// The Box node specifies a rectangular parallelepiped box centred at (0, 0, 0) in the local coordinate system and aligned with the local coordinate axes.
// By default, the box measures 2 units in each dimension, from -1 to +1. The size field specifies the extents of the box along the X-, Y-, and Z-axes
// respectively and each component value shall be greater than zero.
void X3DImporter::ParseNode_Geometry3D_Box()
{
    std::string def, use;
    bool solid = true;
    aiVector3D size(2, 2, 2);
    CX3DImporter_NodeElement* ne( nullptr );

	MACRO_ATTRREAD_LOOPBEG;
		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
		MACRO_ATTRREAD_CHECK_REF("size", size, XML_ReadNode_GetAttrVal_AsVec3f);
		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
	MACRO_ATTRREAD_LOOPEND;

	// if "USE" defined then find already defined element.
	if(!use.empty())
	{
		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Box, ne);
	}
	else
	{
		// create and if needed - define new geometry object.
		ne = new CX3DImporter_NodeElement_Geometry3D(CX3DImporter_NodeElement::ENET_Box, NodeElement_Cur);
		if(!def.empty()) ne->ID = def;

		GeometryHelper_MakeQL_RectParallelepiped(size, ((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices);// get quad list
		((CX3DImporter_NodeElement_Geometry3D*)ne)->Solid = solid;
		((CX3DImporter_NodeElement_Geometry3D*)ne)->NumIndices = 4;
		// check for X3DMetadataObject childs.
		if(!mReader->isEmptyElement())
			ParseNode_Metadata(ne, "Box");
		else
			NodeElement_Cur->Child.push_back(ne);// add made object as child to current element

		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
	}// if(!use.empty()) else
}

// <Cone
// DEF=""           ID
// USE=""           IDREF
// bottom="true"    SFBool [initializeOnly]
// bottomRadius="1" SFloat [initializeOnly]
// height="2"       SFloat [initializeOnly]
// side="true"      SFBool [initializeOnly]
// solid="true"     SFBool [initializeOnly]
// />
void X3DImporter::ParseNode_Geometry3D_Cone()
{
    std::string use, def;
    bool bottom = true;
    float bottomRadius = 1;
    float height = 2;
    bool side = true;
    bool solid = true;
    CX3DImporter_NodeElement* ne( nullptr );

	MACRO_ATTRREAD_LOOPBEG;
		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_RET("side", side, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_RET("bottom", bottom, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_RET("height", height, XML_ReadNode_GetAttrVal_AsFloat);
		MACRO_ATTRREAD_CHECK_RET("bottomRadius", bottomRadius, XML_ReadNode_GetAttrVal_AsFloat);
	MACRO_ATTRREAD_LOOPEND;

	// if "USE" defined then find already defined element.
	if(!use.empty())
	{
		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Cone, ne);
	}
	else
	{
		const unsigned int tess = 30;///TODO: IME tesselation factor thru ai_property

		std::vector<aiVector3D> tvec;// temp array for vertices.

		// create and if needed - define new geometry object.
		ne = new CX3DImporter_NodeElement_Geometry3D(CX3DImporter_NodeElement::ENET_Cone, NodeElement_Cur);
		if(!def.empty()) ne->ID = def;

		// make cone or parts according to flags.
		if(side)
		{
			StandardShapes::MakeCone(height, 0, bottomRadius, tess, tvec, !bottom);
		}
		else if(bottom)
		{
			StandardShapes::MakeCircle(bottomRadius, tess, tvec);
			height = -(height / 2);
			for(std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); it++) it->y = height;// y - because circle made in oXZ.
		}

		// copy data from temp array
		for(std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); it++) ((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices.push_back(*it);

		((CX3DImporter_NodeElement_Geometry3D*)ne)->Solid = solid;
		((CX3DImporter_NodeElement_Geometry3D*)ne)->NumIndices = 3;
		// check for X3DMetadataObject childs.
		if(!mReader->isEmptyElement())
			ParseNode_Metadata(ne, "Cone");
		else
			NodeElement_Cur->Child.push_back(ne);// add made object as child to current element

		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
	}// if(!use.empty()) else
}

// <Cylinder
// DEF=""        ID
// USE=""        IDREF
// bottom="true" SFBool [initializeOnly]
// height="2"    SFloat [initializeOnly]
// radius="1"    SFloat [initializeOnly]
// side="true"   SFBool [initializeOnly]
// solid="true"  SFBool [initializeOnly]
// top="true"    SFBool [initializeOnly]
// />
void X3DImporter::ParseNode_Geometry3D_Cylinder()
{
    std::string use, def;
    bool bottom = true;
    float height = 2;
    float radius = 1;
    bool side = true;
    bool solid = true;
    bool top = true;
    CX3DImporter_NodeElement* ne( nullptr );

	MACRO_ATTRREAD_LOOPBEG;
		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
		MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_RET("bottom", bottom, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_RET("top", top, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_RET("side", side, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_RET("height", height, XML_ReadNode_GetAttrVal_AsFloat);
	MACRO_ATTRREAD_LOOPEND;

	// if "USE" defined then find already defined element.
	if(!use.empty())
	{
		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Cylinder, ne);
	}
	else
	{
		const unsigned int tess = 30;///TODO: IME tesselation factor thru ai_property

		std::vector<aiVector3D> tside;// temp array for vertices of side.
		std::vector<aiVector3D> tcir;// temp array for vertices of circle.

		// create and if needed - define new geometry object.
		ne = new CX3DImporter_NodeElement_Geometry3D(CX3DImporter_NodeElement::ENET_Cylinder, NodeElement_Cur);
		if(!def.empty()) ne->ID = def;

		// make cilynder or parts according to flags.
		if(side) StandardShapes::MakeCone(height, radius, radius, tess, tside, true);

		height /= 2;// height defined for whole cylinder, when creating top and bottom circle we are using just half of height.
		if(top || bottom) StandardShapes::MakeCircle(radius, tess, tcir);
		// copy data from temp arrays
		std::list<aiVector3D>& vlist = ((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices;// just short alias.

		for(std::vector<aiVector3D>::iterator it = tside.begin(); it != tside.end(); it++) vlist.push_back(*it);

		if(top)
		{
			for(std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); it++)
			{
				(*it).y = height;// y - because circle made in oXZ.
				vlist.push_back(*it);
			}
		}// if(top)

		if(bottom)
		{
			for(std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); it++)
			{
				(*it).y = -height;// y - because circle made in oXZ.
				vlist.push_back(*it);
			}
		}// if(top)

		((CX3DImporter_NodeElement_Geometry3D*)ne)->Solid = solid;
		((CX3DImporter_NodeElement_Geometry3D*)ne)->NumIndices = 3;
		// check for X3DMetadataObject childs.
		if(!mReader->isEmptyElement())
			ParseNode_Metadata(ne, "Cylinder");
		else
			NodeElement_Cur->Child.push_back(ne);// add made object as child to current element

		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
	}// if(!use.empty()) else
}

// <ElevationGrid
// DEF=""                 ID
// USE=""                 IDREF
// ccw="true"             SFBool  [initializeOnly]
// colorPerVertex="true"  SFBool  [initializeOnly]
// creaseAngle="0"        SFloat  [initializeOnly]
// height=""              MFloat  [initializeOnly]
// normalPerVertex="true" SFBool  [initializeOnly]
// solid="true"           SFBool  [initializeOnly]
// xDimension="0"         SFInt32 [initializeOnly]
// xSpacing="1.0"         SFloat  [initializeOnly]
// zDimension="0"         SFInt32 [initializeOnly]
// zSpacing="1.0"         SFloat  [initializeOnly]
// >
//   <!-- ColorNormalTexCoordContentModel -->
// ColorNormalTexCoordContentModel can contain Color (or ColorRGBA), Normal and TextureCoordinate, in any order. No more than one instance of any single
// node type is allowed. A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
// </ElevationGrid>
// The ElevationGrid node specifies a uniform rectangular grid of varying height in the Y=0 plane of the local coordinate system. The geometry is described
// by a scalar array of height values that specify the height of a surface above each point of the grid. The xDimension and zDimension fields indicate
// the number of elements of the grid height array in the X and Z directions. Both xDimension and zDimension shall be greater than or equal to zero.
// If either the xDimension or the zDimension is less than two, the ElevationGrid contains no quadrilaterals.
void X3DImporter::ParseNode_Geometry3D_ElevationGrid()
{
    std::string use, def;
    bool ccw = true;
    bool colorPerVertex = true;
    float creaseAngle = 0;
    std::list<float> height;
    bool normalPerVertex = true;
    bool solid = true;
    int32_t xDimension = 0;
    float xSpacing = 1;
    int32_t zDimension = 0;
    float zSpacing = 1;
    CX3DImporter_NodeElement* ne( nullptr );

	MACRO_ATTRREAD_LOOPBEG;
		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
		MACRO_ATTRREAD_CHECK_REF("height", height, XML_ReadNode_GetAttrVal_AsListF);
		MACRO_ATTRREAD_CHECK_RET("xDimension", xDimension, XML_ReadNode_GetAttrVal_AsI32);
		MACRO_ATTRREAD_CHECK_RET("xSpacing", xSpacing, XML_ReadNode_GetAttrVal_AsFloat);
		MACRO_ATTRREAD_CHECK_RET("zDimension", zDimension, XML_ReadNode_GetAttrVal_AsI32);
		MACRO_ATTRREAD_CHECK_RET("zSpacing", zSpacing, XML_ReadNode_GetAttrVal_AsFloat);
	MACRO_ATTRREAD_LOOPEND;

	// if "USE" defined then find already defined element.
	if(!use.empty())
	{
		MACRO_USE_CHECKANDAPPLY(def, use, ENET_ElevationGrid, ne);
	}
	else
	{
		if((xSpacing == 0.0f) || (zSpacing == 0.0f)) throw DeadlyImportError("Spacing in <ElevationGrid> must be grater than zero.");
		if((xDimension <= 0) || (zDimension <= 0)) throw DeadlyImportError("Dimension in <ElevationGrid> must be grater than zero.");
		if((size_t)(xDimension * zDimension) != height.size()) Throw_IncorrectAttrValue("Heights count must be equal to \"xDimension * zDimension\"");

		// create and if needed - define new geometry object.
		ne = new CX3DImporter_NodeElement_ElevationGrid(CX3DImporter_NodeElement::ENET_ElevationGrid, NodeElement_Cur);
		if(!def.empty()) ne->ID = def;

		CX3DImporter_NodeElement_ElevationGrid& grid_alias = *((CX3DImporter_NodeElement_ElevationGrid*)ne);// create alias for conveience

		{// create grid vertices list
			std::list<float>::const_iterator he_it = height.begin();

			for(int32_t zi = 0; zi < zDimension; zi++)// rows
			{
				for(int32_t xi = 0; xi < xDimension; xi++)// columns
				{
					aiVector3D tvec(xSpacing * xi, *he_it, zSpacing * zi);

					grid_alias.Vertices.push_back(tvec);
					he_it++;
				}
			}
		}// END: create grid vertices list
		//
		// create faces list. In "coordIdx" format
		//
		// check if we have quads
		if((xDimension < 2) || (zDimension < 2))// only one element in dimension is set, create line set.
		{
			((CX3DImporter_NodeElement_ElevationGrid*)ne)->NumIndices = 2;// will be holded as line set.
			for(size_t i = 0, i_e = (grid_alias.Vertices.size() - 1); i < i_e; i++)
			{
				grid_alias.CoordIdx.push_back(i);
				grid_alias.CoordIdx.push_back(i + 1);
				grid_alias.CoordIdx.push_back(-1);
			}
		}
		else// two or more elements in every dimension is set. create quad set.
		{
			((CX3DImporter_NodeElement_ElevationGrid*)ne)->NumIndices = 4;
			for(int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++)// rows
			{
				for(int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++)// columns
				{
					// points direction in face.
					if(ccw)
					{
						// CCW:
						//	3 2
						//	0 1
						grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi);
						grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1));
						grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1));
						grid_alias.CoordIdx.push_back(fzi * xDimension + fxi);
					}
					else
					{
						// CW:
						//	0 1
						//	3 2
						grid_alias.CoordIdx.push_back(fzi * xDimension + fxi);
						grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1));
						grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1));
						grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi);
					}// if(ccw) else

					grid_alias.CoordIdx.push_back(-1);
				}// for(int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++)
			}// for(int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++)
		}// if((xDimension < 2) || (zDimension < 2)) else

		grid_alias.ColorPerVertex = colorPerVertex;
		grid_alias.NormalPerVertex = normalPerVertex;
		grid_alias.CreaseAngle = creaseAngle;
		grid_alias.Solid = solid;
        // check for child nodes
        if(!mReader->isEmptyElement())
        {
			ParseHelper_Node_Enter(ne);
			MACRO_NODECHECK_LOOPBEGIN("ElevationGrid");
				// check for X3DComposedGeometryNodes
				if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
				if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
				if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
				if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
				// check for X3DMetadataObject
				if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("ElevationGrid");

			MACRO_NODECHECK_LOOPEND("ElevationGrid");
			ParseHelper_Node_Exit();
		}// if(!mReader->isEmptyElement())
		else
		{
			NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
		}// if(!mReader->isEmptyElement()) else

		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
	}// if(!use.empty()) else
}

template<typename TVector>
static void GeometryHelper_Extrusion_CurveIsClosed(std::vector<TVector>& pCurve, const bool pDropTail, const bool pRemoveLastPoint, bool& pCurveIsClosed)
{
    size_t cur_sz = pCurve.size();

	pCurveIsClosed = false;
	// for curve with less than four points checking is have no sense,
	if(cur_sz < 4) return;

	for(size_t s = 3, s_e = cur_sz; s < s_e; s++)
	{
		// search for first point of duplicated part.
		if(pCurve[0] == pCurve[s])
		{
			bool found = true;

			// check if tail(indexed by b2) is duplicate of head(indexed by b1).
			for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++)
			{
				if(pCurve[b1] != pCurve[b2])
				{// points not match: clear flag and break loop.
					found = false;

					break;
				}
			}// for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++)

			// if duplicate tail is found then drop or not it depending on flags.
			if(found)
			{
				pCurveIsClosed = true;
				if(pDropTail)
				{
					if(!pRemoveLastPoint) s++;// prepare value for iterator's arithmetics.

					pCurve.erase(pCurve.begin() + s, pCurve.end());// remove tail
				}

				break;
			}// if(found)
		}// if(pCurve[0] == pCurve[s])
	}// for(size_t s = 3, s_e = (cur_sz - 1); s < s_e; s++)
}

static aiVector3D GeometryHelper_Extrusion_GetNextY(const size_t pSpine_PointIdx, const std::vector<aiVector3D>& pSpine, const bool pSpine_Closed)
{
    const size_t spine_idx_last = pSpine.size() - 1;
    aiVector3D tvec;

	if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last))// at first special cases
	{
		if(pSpine_Closed)
		{// If the spine curve is closed: The SCP for the first and last points is the same and is found using (spine[1] − spine[n − 2]) to compute the Y-axis.
			// As we even for closed spine curve last and first point in pSpine are not the same: duplicates(spine[n - 1] which are equivalent to spine[0])
			// in tail are removed.
			// So, last point in pSpine is a spine[n - 2]
			tvec = pSpine[1] - pSpine[spine_idx_last];
		}
		else if(pSpine_PointIdx == 0)
		{// The Y-axis used for the first point is the vector from spine[0] to spine[1]
			tvec = pSpine[1] - pSpine[0];
		}
		else
		{// The Y-axis used for the last point it is the vector from spine[n−2] to spine[n−1]. In our case(see above about droping tail) spine[n - 1] is
			// the spine[0].
			tvec = pSpine[spine_idx_last] - pSpine[spine_idx_last - 1];
		}
	}// if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last))
	else
	{// For all points other than the first or last: The Y-axis for spine[i] is found by normalizing the vector defined by (spine[i+1] − spine[i−1]).
		tvec = pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx - 1];
	}// if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) else

	return tvec.Normalize();
}

static aiVector3D GeometryHelper_Extrusion_GetNextZ(const size_t pSpine_PointIdx, const std::vector<aiVector3D>& pSpine, const bool pSpine_Closed,
													const aiVector3D pVecZ_Prev)
{
    const aiVector3D zero_vec(0);
    const size_t spine_idx_last = pSpine.size() - 1;

    aiVector3D tvec;

	// at first special cases
	if(pSpine.size() < 3)// spine have not enough points for vector calculations.
	{
		tvec.Set(0, 0, 1);
	}
	else if(pSpine_PointIdx == 0)// special case: first point
	{
		if(pSpine_Closed)// for calculating use previous point in curve s[n - 2]. In list it's a last point, because point s[n - 1] was removed as duplicate.
		{
			tvec = (pSpine[1] - pSpine[0]) ^ (pSpine[spine_idx_last] - pSpine[0]);
		}
		else // for not closed curve first and next point(s[0] and s[1]) has the same vector Z.
		{
			bool found = false;

			// As said: "If the Z-axis of the first point is undefined (because the spine is not closed and the first two spine segments are collinear)
			// then the Z-axis for the first spine point with a defined Z-axis is used."
			// Walk thru spine and find Z.
			for(size_t next_point = 2; (next_point <= spine_idx_last) && !found; next_point++)
			{
				// (pSpine[2] - pSpine[1]) ^ (pSpine[0] - pSpine[1])
				tvec = (pSpine[next_point] - pSpine[next_point - 1]) ^ (pSpine[next_point - 2] - pSpine[next_point - 1]);
				found = !tvec.Equal(zero_vec);
			}

			// if entire spine are collinear then use OZ axis.
			if(!found) tvec.Set(0, 0, 1);
		}// if(pSpine_Closed) else
	}// else if(pSpine_PointIdx == 0)
	else if(pSpine_PointIdx == spine_idx_last)// special case: last point
	{
		if(pSpine_Closed)
		{// do not forget that real last point s[n - 1] is removed as duplicated. And in this case we are calculating vector Z for point s[n - 2].
			tvec = (pSpine[0] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]);
			// if taken spine vectors are collinear then use previous vector Z.
			if(tvec.Equal(zero_vec)) tvec = pVecZ_Prev;
		}
		else
		{// vector Z for last point of not closed curve is previous vector Z.
			tvec = pVecZ_Prev;
		}
	}
	else// regular point
	{
		tvec = (pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]);
		// if taken spine vectors are collinear then use previous vector Z.
		if(tvec.Equal(zero_vec)) tvec = pVecZ_Prev;
	}

	// After determining the Z-axis, its dot product with the Z-axis of the previous spine point is computed. If this value is negative, the Z-axis
	// is flipped (multiplied by −1).
	if((tvec * pVecZ_Prev) < 0) tvec = -tvec;

	return tvec.Normalize();
}

// <Extrusion
// DEF=""                                 ID
// USE=""                                 IDREF
// beginCap="true"                        SFBool     [initializeOnly]
// ccw="true"                             SFBool     [initializeOnly]
// convex="true"                          SFBool     [initializeOnly]
// creaseAngle="0.0"                      SFloat     [initializeOnly]
// crossSection="1 1 1 -1 -1 -1 -1 1 1 1" MFVec2f    [initializeOnly]
// endCap="true"                          SFBool     [initializeOnly]
// orientation="0 0 1 0"                  MFRotation [initializeOnly]
// scale="1 1"                            MFVec2f    [initializeOnly]
// solid="true"                           SFBool     [initializeOnly]
// spine="0 0 0 0 1 0"                    MFVec3f    [initializeOnly]
// />
void X3DImporter::ParseNode_Geometry3D_Extrusion()
{
    std::string use, def;
    bool beginCap = true;
    bool ccw = true;
    bool convex = true;
    float creaseAngle = 0;
    std::vector<aiVector2D> crossSection;
    bool endCap = true;
    std::vector<float> orientation;
    std::vector<aiVector2D> scale;
    bool solid = true;
    std::vector<aiVector3D> spine;
    CX3DImporter_NodeElement* ne( nullptr );

	MACRO_ATTRREAD_LOOPBEG;
		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
		MACRO_ATTRREAD_CHECK_RET("beginCap", beginCap, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_RET("convex", convex, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
		MACRO_ATTRREAD_CHECK_REF("crossSection", crossSection, XML_ReadNode_GetAttrVal_AsArrVec2f);
		MACRO_ATTRREAD_CHECK_RET("endCap", endCap, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_REF("orientation", orientation, XML_ReadNode_GetAttrVal_AsArrF);
		MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsArrVec2f);
		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_REF("spine", spine, XML_ReadNode_GetAttrVal_AsArrVec3f);
	MACRO_ATTRREAD_LOOPEND;

	// if "USE" defined then find already defined element.
	if(!use.empty())
	{
		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Extrusion, ne);
	}
	else
	{
		//
		// check if default values must be assigned
		//
		if(spine.size() == 0)
		{
			spine.resize(2);
			spine[0].Set(0, 0, 0), spine[1].Set(0, 1, 0);
		}
		else if(spine.size() == 1)
		{
			throw DeadlyImportError("ParseNode_Geometry3D_Extrusion. Spine must have at least two points.");
		}

		if(crossSection.size() == 0)
		{
			crossSection.resize(5);
			crossSection[0].Set(1, 1), crossSection[1].Set(1, -1), crossSection[2].Set(-1, -1), crossSection[3].Set(-1, 1), crossSection[4].Set(1, 1);
		}

		{// orientation
			size_t ori_size = orientation.size() / 4;

			if(ori_size < spine.size())
			{
				float add_ori[4];// values that will be added

				if(ori_size == 1)// if "orientation" has one element(means one MFRotation with four components) then use it value for all spine points.
				{
					add_ori[0] = orientation[0], add_ori[1] = orientation[1], add_ori[2] = orientation[2], add_ori[3] = orientation[3];
				}
				else// else - use default values
				{
					add_ori[0] = 0, add_ori[1] = 0, add_ori[2] = 1, add_ori[3] = 0;
				}

				orientation.reserve(spine.size() * 4);
				for(size_t i = 0, i_e = (spine.size() - ori_size); i < i_e; i++)
					orientation.push_back(add_ori[0]), orientation.push_back(add_ori[1]), orientation.push_back(add_ori[2]), orientation.push_back(add_ori[3]);
			}

			if(orientation.size() % 4) throw DeadlyImportError("Attribute \"orientation\" in <Extrusion> must has multiple four quantity of numbers.");
		}// END: orientation

		{// scale
			if(scale.size() < spine.size())
			{
				aiVector2D add_sc;

				if(scale.size() == 1)// if "scale" has one element then use it value for all spine points.
					add_sc = scale[0];
				else// else - use default values
					add_sc.Set(1, 1);

				scale.reserve(spine.size());
				for(size_t i = 0, i_e = (spine.size() - scale.size()); i < i_e; i++) scale.push_back(add_sc);
			}
		}// END: scale
		//
		// create and if needed - define new geometry object.
		//
		ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_Extrusion, NodeElement_Cur);
		if(!def.empty()) ne->ID = def;

		CX3DImporter_NodeElement_IndexedSet& ext_alias = *((CX3DImporter_NodeElement_IndexedSet*)ne);// create alias for conveience
		// assign part of input data
		ext_alias.CCW = ccw;
		ext_alias.Convex = convex;
		ext_alias.CreaseAngle = creaseAngle;
		ext_alias.Solid = solid;

		//
		// How we done it at all?
		// 1. At first we will calculate array of basises for every point in spine(look SCP in ISO-dic). Also "orientation" vector
		// are applied vor every basis.
		// 2. After that we can create array of point sets: which are scaled, transfered to basis of relative basis and at final translated to real position
		// using relative spine point.
		// 3. Next step is creating CoordIdx array(do not forget "-1" delimiter). While creating CoordIdx also created faces for begin and end caps, if
		// needed. While createing CootdIdx is taking in account CCW flag.
		// 4. The last step: create Vertices list.
		//
        bool spine_closed;// flag: true if spine curve is closed.
        bool cross_closed;// flag: true if cross curve is closed.
        std::vector<aiMatrix3x3> basis_arr;// array of basises. ROW_a - X, ROW_b - Y, ROW_c - Z.
        std::vector<std::vector<aiVector3D> > pointset_arr;// array of point sets: cross curves.

        // detect closed curves
        GeometryHelper_Extrusion_CurveIsClosed(crossSection, true, true, cross_closed);// true - drop tail, true - remove duplicate end.
        GeometryHelper_Extrusion_CurveIsClosed(spine, true, true, spine_closed);// true - drop tail, true - remove duplicate end.
        // If both cap are requested and spine curve is closed then we can make only one cap. Because second cap will be the same surface.
        if(spine_closed)
        {
			beginCap |= endCap;
			endCap = false;
		}

        {// 1. Calculate array of basises.
			aiMatrix4x4 rotmat;
			aiVector3D vecX(0), vecY(0), vecZ(0);

			basis_arr.resize(spine.size());
			for(size_t i = 0, i_e = spine.size(); i < i_e; i++)
			{
				aiVector3D tvec;

				// get axises of basis.
				vecY = GeometryHelper_Extrusion_GetNextY(i, spine, spine_closed);
				vecZ = GeometryHelper_Extrusion_GetNextZ(i, spine, spine_closed, vecZ);
				vecX = (vecY ^ vecZ).Normalize();
				// get rotation matrix and apply "orientation" to basis
				aiMatrix4x4::Rotation(orientation[i * 4 + 3], aiVector3D(orientation[i * 4], orientation[i * 4 + 1], orientation[i * 4 + 2]), rotmat);
				tvec = vecX, tvec *= rotmat, basis_arr[i].a1 = tvec.x, basis_arr[i].a2 = tvec.y, basis_arr[i].a3 = tvec.z;
				tvec = vecY, tvec *= rotmat, basis_arr[i].b1 = tvec.x, basis_arr[i].b2 = tvec.y, basis_arr[i].b3 = tvec.z;
				tvec = vecZ, tvec *= rotmat, basis_arr[i].c1 = tvec.x, basis_arr[i].c2 = tvec.y, basis_arr[i].c3 = tvec.z;
			}// for(size_t i = 0, i_e = spine.size(); i < i_e; i++)
		}// END: 1. Calculate array of basises

		{// 2. Create array of point sets.
			aiMatrix4x4 scmat;
			std::vector<aiVector3D> tcross(crossSection.size());

			pointset_arr.resize(spine.size());
			for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++)
			{
				aiVector3D tc23vec;

				tc23vec.Set(scale[spi].x, 0, scale[spi].y);
				aiMatrix4x4::Scaling(tc23vec, scmat);
				for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++)
				{
					aiVector3D tvecX, tvecY, tvecZ;

					tc23vec.Set(crossSection[cri].x, 0, crossSection[cri].y);
					// apply scaling to point
					tcross[cri] = scmat * tc23vec;
					//
					// transfer point to new basis
					// calculate coordinate in new basis
					tvecX.Set(basis_arr[spi].a1, basis_arr[spi].a2, basis_arr[spi].a3), tvecX *= tcross[cri].x;
					tvecY.Set(basis_arr[spi].b1, basis_arr[spi].b2, basis_arr[spi].b3), tvecY *= tcross[cri].y;
					tvecZ.Set(basis_arr[spi].c1, basis_arr[spi].c2, basis_arr[spi].c3), tvecZ *= tcross[cri].z;
					// apply new coordinates and translate it to spine point.
					tcross[cri] = tvecX + tvecY + tvecZ + spine[spi];
				}// for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; i++)

				pointset_arr[spi] = tcross;// store transfered point set
			}// for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; i++)
		}// END: 2. Create array of point sets.

		{// 3. Create CoordIdx.
			// add caps if needed
			if(beginCap)
			{
				// add cap as polygon. vertices of cap are places at begin, so just add numbers from zero.
				for(size_t i = 0, i_e = crossSection.size(); i < i_e; i++) ext_alias.CoordIndex.push_back(i);

				// add delimiter
				ext_alias.CoordIndex.push_back(-1);
			}// if(beginCap)

			if(endCap)
			{
				// add cap as polygon. vertices of cap are places at end, as for beginCap use just sequence of numbers but with offset.
				size_t beg = (pointset_arr.size() - 1) * crossSection.size();

				for(size_t i = beg, i_e = (beg + crossSection.size()); i < i_e; i++) ext_alias.CoordIndex.push_back(i);

				// add delimiter
				ext_alias.CoordIndex.push_back(-1);
			}// if(beginCap)

			// add quads
			for(size_t spi = 0, spi_e = (spine.size() - 1); spi <= spi_e; spi++)
			{
				const size_t cr_sz = crossSection.size();
				const size_t cr_last = crossSection.size() - 1;

				size_t right_col;// hold index basis for points of quad placed in right column;

				if(spi != spi_e)
					right_col = spi + 1;
				else if(spine_closed)// if spine curve is closed then one more quad is needed: between first and last points of curve.
					right_col = 0;
				else
					break;// if spine curve is not closed then break the loop, because spi is out of range for that type of spine.

				for(size_t cri = 0; cri < cr_sz; cri++)
				{
					if(cri != cr_last)
					{
						MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex,
											spi * cr_sz + cri, right_col * cr_sz + cri, right_col * cr_sz + cri + 1, spi * cr_sz + cri + 1);
						// add delimiter
						ext_alias.CoordIndex.push_back(-1);
					}
					else if(cross_closed)// if cross curve is closed then one more quad is needed: between first and last points of curve.
					{
						MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex,
											spi * cr_sz + cri, right_col * cr_sz + cri, right_col * cr_sz + 0, spi * cr_sz + 0);
						// add delimiter
						ext_alias.CoordIndex.push_back(-1);
					}
				}// for(size_t cri = 0; cri < cr_sz; cri++)
			}// for(size_t spi = 0, spi_e = (spine.size() - 2); spi < spi_e; spi++)
		}// END: 3. Create CoordIdx.

		{// 4. Create vertices list.
			// just copy all vertices
			for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++)
			{
				for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++)
				{
					ext_alias.Vertices.push_back(pointset_arr[spi][cri]);
				}
			}
		}// END: 4. Create vertices list.
//PrintVectorSet("Ext. CoordIdx", ext_alias.CoordIndex);
//PrintVectorSet("Ext. Vertices", ext_alias.Vertices);
		// check for child nodes
		if(!mReader->isEmptyElement())
			ParseNode_Metadata(ne, "Extrusion");
		else
			NodeElement_Cur->Child.push_back(ne);// add made object as child to current element

		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
	}// if(!use.empty()) else
}

// <IndexedFaceSet
// DEF=""                         ID
// USE=""                         IDREF
// ccw="true"             SFBool  [initializeOnly]
// colorIndex=""          MFInt32 [initializeOnly]
// colorPerVertex="true"  SFBool  [initializeOnly]
// convex="true"          SFBool  [initializeOnly]
// coordIndex=""          MFInt32 [initializeOnly]
// creaseAngle="0"        SFFloat [initializeOnly]
// normalIndex=""         MFInt32 [initializeOnly]
// normalPerVertex="true" SFBool  [initializeOnly]
// solid="true"           SFBool  [initializeOnly]
// texCoordIndex=""       MFInt32 [initializeOnly]
// >
//    <!-- ComposedGeometryContentModel -->
// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
// </IndexedFaceSet>
void X3DImporter::ParseNode_Geometry3D_IndexedFaceSet()
{
    std::string use, def;
    bool ccw = true;
    std::list<int32_t> colorIndex;
    bool colorPerVertex = true;
    bool convex = true;
    std::list<int32_t> coordIndex;
    float creaseAngle = 0;
    std::list<int32_t> normalIndex;
    bool normalPerVertex = true;
    bool solid = true;
    std::list<int32_t> texCoordIndex;
    CX3DImporter_NodeElement* ne( nullptr );

	MACRO_ATTRREAD_LOOPBEG;
		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsListI32);
		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_RET("convex", convex, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsListI32);
		MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
		MACRO_ATTRREAD_CHECK_REF("normalIndex", normalIndex, XML_ReadNode_GetAttrVal_AsListI32);
		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
		MACRO_ATTRREAD_CHECK_REF("texCoordIndex", texCoordIndex, XML_ReadNode_GetAttrVal_AsListI32);
	MACRO_ATTRREAD_LOOPEND;

	// if "USE" defined then find already defined element.
	if(!use.empty())
	{
		MACRO_USE_CHECKANDAPPLY(def, use, ENET_IndexedFaceSet, ne);
	}
	else
	{
		// check data
		if(coordIndex.size() == 0) throw DeadlyImportError("IndexedFaceSet must contain not empty \"coordIndex\" attribute.");

		// create and if needed - define new geometry object.
		ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_IndexedFaceSet, NodeElement_Cur);
		if(!def.empty()) ne->ID = def;

		CX3DImporter_NodeElement_IndexedSet& ne_alias = *((CX3DImporter_NodeElement_IndexedSet*)ne);

		ne_alias.CCW = ccw;
		ne_alias.ColorIndex = colorIndex;
		ne_alias.ColorPerVertex = colorPerVertex;
		ne_alias.Convex = convex;
		ne_alias.CoordIndex = coordIndex;
		ne_alias.CreaseAngle = creaseAngle;
		ne_alias.NormalIndex = normalIndex;
		ne_alias.NormalPerVertex = normalPerVertex;
		ne_alias.Solid = solid;
		ne_alias.TexCoordIndex = texCoordIndex;
        // check for child nodes
        if(!mReader->isEmptyElement())
        {
			ParseHelper_Node_Enter(ne);
			MACRO_NODECHECK_LOOPBEGIN("IndexedFaceSet");
				// check for X3DComposedGeometryNodes
				if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
				if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
				if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
				if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
				if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
				// check for X3DMetadataObject
				if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedFaceSet");

			MACRO_NODECHECK_LOOPEND("IndexedFaceSet");
			ParseHelper_Node_Exit();
		}// if(!mReader->isEmptyElement())
		else
		{
			NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
		}

		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
	}// if(!use.empty()) else
}

// <Sphere
// DEF=""       ID
// USE=""       IDREF
// radius="1"   SFloat [initializeOnly]
// solid="true" SFBool [initializeOnly]
// />
void X3DImporter::ParseNode_Geometry3D_Sphere()
{
    std::string use, def;
    float radius = 1;
    bool solid = true;
    CX3DImporter_NodeElement* ne( nullptr );

	MACRO_ATTRREAD_LOOPBEG;
		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
		MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
	MACRO_ATTRREAD_LOOPEND;

	// if "USE" defined then find already defined element.
	if(!use.empty())
	{
		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Sphere, ne);
	}
	else
	{
		const unsigned int tess = 3;///TODO: IME tesselation factor thru ai_property

		std::vector<aiVector3D> tlist;

		// create and if needed - define new geometry object.
		ne = new CX3DImporter_NodeElement_Geometry3D(CX3DImporter_NodeElement::ENET_Sphere, NodeElement_Cur);
		if(!def.empty()) ne->ID = def;

		StandardShapes::MakeSphere(tess, tlist);
		// copy data from temp array and apply scale
		for(std::vector<aiVector3D>::iterator it = tlist.begin(); it != tlist.end(); it++)
		{
			((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices.push_back(*it * radius);
		}

		((CX3DImporter_NodeElement_Geometry3D*)ne)->Solid = solid;
		((CX3DImporter_NodeElement_Geometry3D*)ne)->NumIndices = 3;
		// check for X3DMetadataObject childs.
		if(!mReader->isEmptyElement())
			ParseNode_Metadata(ne, "Sphere");
		else
			NodeElement_Cur->Child.push_back(ne);// add made object as child to current element

		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
	}// if(!use.empty()) else
}

}// namespace Assimp

#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER


text:
/**
 *     This code was auto-generated by a Codezu.
 *
 *     Changes to this file may cause incorrect behavior and will be lost if
 *     the code is regenerated.
 */
package com.mozu.api.resources.commerce.shipping.admin;

import com.mozu.api.ApiContext;
import org.joda.time.DateTime;
import java.util.List;
import java.util.ArrayList;
import com.mozu.api.MozuClient;
import com.mozu.api.MozuClientFactory;
import com.mozu.api.MozuUrl;
import com.mozu.api.Headers;
import com.mozu.api.AsyncCallback;
import java.util.concurrent.CountDownLatch;

import com.mozu.api.security.AuthTicket;
import org.apache.commons.lang.StringUtils;

/**
 *
 *
 */
public class ShippingProfileResource {
	///
	/// <see cref="Mozu.Api.ApiContext"/>
	///
	private ApiContext _apiContext;

	public ShippingProfileResource(ApiContext apiContext)
	{
		_apiContext = apiContext;
	}

	/**
	 *
	 *

	 *	ShippingProfile shippingprofile = new ShippingProfile();
	 *	ShippingProfileCollection shippingProfileCollection = shippingprofile.getProfiles();
	 *

	 * @param dataViewMode DataViewMode
	 * @return com.mozu.api.contracts.shippingadmin.profile.ShippingProfileCollection
	 * @see com.mozu.api.contracts.shippingadmin.profile.ShippingProfileCollection
	 */
	public com.mozu.api.contracts.shippingadmin.profile.ShippingProfileCollection getProfiles() throws Exception
	{
		return getProfiles( null);
	}

	/**
	 *
	 *

	 *	ShippingProfile shippingprofile = new ShippingProfile();
	 *	CountDownLatch latch = shippingprofile.getProfiles( callback );
	 *	latch.await()	 *

	 * @param  callback callback handler for asynchronous operations
	 * @param dataViewMode DataViewMode
	 * @return com.mozu.api.contracts.shippingadmin.profile.ShippingProfileCollection
	 * @see com.mozu.api.contracts.shippingadmin.profile.ShippingProfileCollection
	 */
	public CountDownLatch getProfilesAsync( AsyncCallback<com.mozu.api.contracts.shippingadmin.profile.ShippingProfileCollection> callback) throws Exception
	{
		return getProfilesAsync( null, callback);
	}

	/**
	 *
	 *

	 *	ShippingProfile shippingprofile = new ShippingProfile();
	 *	ShippingProfileCollection shippingProfileCollection = shippingprofile.getProfiles( responseFields);
	 *

	 * @param responseFields
	 * @param dataViewMode DataViewMode
	 * @return com.mozu.api.contracts.shippingadmin.profile.ShippingProfileCollection
	 * @see com.mozu.api.contracts.shippingadmin.profile.ShippingProfileCollection
	 */
	public com.mozu.api.contracts.shippingadmin.profile.ShippingProfileCollection getProfiles(String responseFields) throws Exception
	{
		MozuClient<com.mozu.api.contracts.shippingadmin.profile.ShippingProfileCollection> client = com.mozu.api.clients.commerce.shipping.admin.ShippingProfileClient.getProfilesClient( responseFields);
		client.setContext(_apiContext);
		client.executeRequest();
		return client.getResult();

	}

	/**
	 *
	 *

	 *	ShippingProfile shippingprofile = new ShippingProfile();
	 *	CountDownLatch latch = shippingprofile.getProfiles( responseFields, callback );
	 *	latch.await()	 *

	 * @param responseFields
	 * @param  callback callback handler for asynchronous operations
	 * @param dataViewMode DataViewMode
	 * @return com.mozu.api.contracts.shippingadmin.profile.ShippingProfileCollection
	 * @see com.mozu.api.contracts.shippingadmin.profile.ShippingProfileCollection
	 */
	public CountDownLatch getProfilesAsync(String responseFields, AsyncCallback<com.mozu.api.contracts.shippingadmin.profile.ShippingProfileCollection> callback) throws Exception
	{
		MozuClient<com.mozu.api.contracts.shippingadmin.profile.ShippingProfileCollection> client = com.mozu.api.clients.commerce.shipping.admin.ShippingProfileClient.getProfilesClient( responseFields);
		client.setContext(_apiContext);
		return client.executeRequest(callback);

	}

}


text:
package net.dv8tion.jda.api.entities.channel.concrete;

import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.channel.attribute.ISlowmodeChannel;
import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel;
import net.dv8tion.jda.api.managers.channel.concrete.TextChannelManager;
import net.dv8tion.jda.api.requests.restaction.ChannelAction;

import javax.annotation.Nonnull;

/**
 * Represents a Discord Text GuildChannel.
 *
Adds additional functionality and information for text channels in Discord,
 * on top of the common functionality present in other guild message channels.
 *
 *
This is a {@link net.dv8tion.jda.api.entities.channel.middleman.GuildChannel GuildChannel} capable of sending messages.
 *
 * @see net.dv8tion.jda.api.entities.channel.middleman.GuildChannel
 * @see net.dv8tion.jda.api.entities.channel.middleman.MessageChannel
 * @see net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel
 *
 * @see   Guild#getTextChannelCache()
 * @see   Guild#getTextChannels()
 * @see   Guild#getTextChannelsByName(String, boolean)
 * @see   Guild#getTextChannelById(long)
 *
 * @see   JDA#getTextChannelCache()
 * @see   JDA#getTextChannels()
 * @see   JDA#getTextChannelsByName(String, boolean)
 * @see   JDA#getTextChannelById(long)
 */
public interface TextChannel extends StandardGuildMessageChannel, ISlowmodeChannel
{
    @Nonnull
    @Override
    ChannelAction<TextChannel> createCopy(@Nonnull Guild guild);

    @Nonnull
    @Override
    default ChannelAction<TextChannel> createCopy()
    {
        return createCopy(getGuild());
    }

    @Nonnull
    @Override
    TextChannelManager getManager();
}