Sobre estereologia, OpenGL, PhysX e CUDA

Eu estava pensando nesse post há um bom tempo. Falar um pouco do meu TCC. A idéia por trás de todo esse trabalho é um área interdisciplinar conhecida por estereologia. Sendo bem direto, o objetivo da estereologia é a interpretação tridimensional (3D) de uma imagem plana (2D). Ela provê tecnicas para extrair informação quantitativa sobre materiais 3D à partir de medições feitas em seções planares. Ela é uma importante ferramenta para a microscopia particularmente o estudo do petróleo, histologia, neuroanatomia e ciência dos materiais. Entre suas aplicações, posso citar o estudo da composição de materiais rígidos, determinação de volume, superfície à partir de simples seções bidimensionais de uma estrutura.

Imagine que você deseja estudar a composição de um metal, cristal ou de um tecido de algum orgão animal ou vegetal. Para isso, você tem uma lâmina retangular, suficientemente grande e bem fina para transpor o objeto que você deseja estudar. Imagina então que depois que você retirar a lâmina, ela conterá imagens de todas as intersecções alcançadas, por exemplo, se a estrutura que está sendo estudada é composta por pequenos corpos totalmente esféricos, quando nosso plano de corte transpor o objeto em estudo e for retirado ele terá registros de instersecções circulares. As seguintes imagens exemplificam:

  1. Considere uma rocha, com um formato cúbico. Considere então que as estruturas internas (pequenas esferas) sejam os elementos que a compõe.

2.  Agora considere o corte em algum ponto da rocha pela lâmina (plano de corte, como é mais conhecido):

3. Agora apenas os objetos interceptados pela lâmina de corte (plano de corte) são considerados:

4) Agora, para as esferas interceptadas o plano de corte obtem as regiões interceptadas. Neste caso, apenas esferas compõe a estrutura portanto as regiões interceptadas serão círculos.

Os dados finais que irão inferir os parâmetros tridimensionais da estrutura original são deduzidos à partir de várias informações bidimensionais coletadas por vários planos diferentes. Este exemplo é simples, foi apenas demonstrado esferas. Estruturas reais são muito mais complexas,  como no caso do metal duro (explicado mais adiante) onde são encontrados componentes em forma de prismas triangulares e prismas triangulares truncados resultando em polígonos quando interceptados pelo plano de corte, onde exigiu um pouco mais de pesquisa em geometria computacional.

Simulações computacionais tem lá seus prós e contras. O grande ponto positivo, é que, dado um evento real não observável à olho nú e as variáveis que o condicionam, uma simulação computacional permite um estudo sobre o mesmo sem grandes necessidade imediata de investimento em laboratórios e maquinário científico. O ponto negativo, é que o modelo representado por uma computação é aproximado. Você sempre estará limitado numericamente, há uma perda de aproximação da transição de um modelo matemático para um computacional. Entretanto, com o advento de CPU’s multicore e unidades de processamento gráficas de propósito geral (GPU) as simulações são levadas à um outro nível de acurácia em seus resultados, principalmente ao levar em conta o nível microscópico dos objetos de estudo da estereologia. É impraticável, enfadonho e susceptível ao erro todo o processo manual baseado em observações microscópicas. Aí está a justificativa para este trabalho.

O metal duro é o material compósito constituído de uma fase dura dispersa em uma fase dúctil. A fase dura consiste em grãos de carbeto de tungstênio (WC) e a fase dúctil e ligante é constituída, principalmente, por cobalto (Co), entretanto níquel e ferro também podem ser utilizados. A grande sacada de estudar e construir materiais compósitos é a combinação de várias características dos elementos compositores. Como resultado disto (WC + Co), é obtido um material que combina boa resistência à fratura e alta dureza a temperaturas elevadas. Quanto às aplicações, o metal duro apresenta diversas. Sendo que as ferramentas de corte constituem a principal aplicação. Uma aplicação especial do metal duro, produzido com pós finos ou ultrafinos, envolvendo grandes quantidades de carbeto cementado, está na produção de brocas para a realização de furos (muito pequenos) em placas de circuitos impressos para computadores e na indústria  de eletrônicos. Para este propósito, novas composições de metal duro, baseadas em carbetos com granulações extremamente finas têm sido desenvolvidas.

Em 2006, um trabalho desenvolvido por um doutorando pela UENF desenvolveu uma simulação com esse objetivo. O grande problema foi  que a biblioteca de simulação física utilizada não permitia uma simulação realista do metal duro, o máximo atingido era um bloco de metal duro composto por 500 elementos compósitos (Wc e Co). O que não chega muito próximo da realidade. Minha implementação vai além disso, além de utilizar algumas ferramentas que permitiram a paralelização de alguns algoritmos rodando em uma Geforce 9600 Gt.

O Objetivo final, é a implementação de rotinas estereológicas em grãos de metal duro através de uma simulação computacional para enfim comparar os resultados obtidos com os resultados presentes na literatura (estes sim, práticos) e de simulações anteriores para enfim demonstrar o avanço alcançado com uma implementação cujo processamento roda em placas gráficas de propósito geral e de baixo custo.

Deixe um comentário

Arquivado em C++, Computação Gráfica, OpenGL, QT, TCC

Presos ao Desktop

É incrível: estamos amarrados ao Desktop. Seja qual for o Framework,  Toolkit, SDK, metologia … fique a vontade, você ainda sim estará amarrado ao Desktop. Estou convivendo com este empecilho em sistemas Web de automação comercial desenvolvidos na NetSoft, empresa em que trabalho. Dependemos de impressoras fiscais, impressoras matriciais, PinPads, leitores de código de barras e aí vai …  Para a nossa solução ser completamente Web, desenvolvemos Applets Java para integrar soluções Web2.0 com recursos de Hardware da máquina cliente. Isso é um testemunho pessoal de que depender dos “outros” nem sempre é uma boa escolha. Quer um exemplo neste contexto: Adivinha como se utiliza impressora matricial em Java. Uma API de alto-nível utilizando JNI? Simplesmente mandar o conteúdo para impressora? Antes fosse! É uma verdadeira brincadeira de mau gosto: Abra um stream diretamente na porta paralela da impressora e a envie todos os comandos necessários para gerenciar tabulações, parágrafos e quebras de linha para formatar os dados … legal né ?? Ainda não existe uma plataforma Web homogênea de desenvolvimento para automação comercial, penso eu. Assim como dependemos de compiladores, linguagens, servidores e browsers dependemos de fabricantes às vezes muito pouco preucupados com o desenvolvedor. Falta documentação, assistência, exemplos e organização em muitos fornecedores. No mercado poucas são as soluções 100% Web neste nicho devido à estas restrinções, embora exista todo um conjunto significativo de pontos positivos que favorecem a plataforma Web, principalmente o deployment, tão crítico e importante para softwares em processo de “amadurecimento”. Optamos pela Web, 100% Web.

Deixe um comentário

Arquivado em Grails, Groovy, Java, Uncategorized, Web

Street Fighter: Ryu x Ken em XNA, primeiros passos

Dei meus primeiros passos na minha versão XNA do Street Fighter. Por enquanto a missão é colocar os personagens Ryu e Ken p/ lutarem ( quem sabe não expando para os outros personagens também :-) ). Implementei 4 (quatro) “chutões” do Ryu e a posição de descanso do mesmo (gingando), definindo assim a arquitetura geral do game. Ainda falta outros golpes (hadouken!) e definir como dar um comportamento inteligente ao oponente do lutador controlado pelo jogador.

Código fonte:

http://github.com/lucassimao/XNA-Street-Fighter

Alguns screenshots:

foto4

foto4

foto4

foto4

8 Comentários

Arquivado em desenvolvimento, Games, Xbox 360, XNA

Do que não gostei em ruby …

  • Constantes em ruby permitem atribuições posteriores, lançando avisos … (Contantes não eram p/ ser constantes?)
  • Variáveis globais …
  • Sem suporte à sobrecarga de métodos de forma direta
  • Green Threads : As threads não são nativas, são “emuladas” pelo interpretador …
  • Não tem operador de auto-incremento :-(
  • Variáveis locais definidas no corpo dos loops until, for e while são “largados” tornando-se disponíveis no escopo global … Por isso não uso o laço for em ruby diretamente, ao invés, prefiro iterators.
i=true
while(i)
   i=false
   a=2
end
puts defined?(a) // retorna true
  • Pessoalmente, ñ uma crítica, não confio em escrever um bloco de código cujo valor seja denotado pela última expressão
  • Catch e throw me parece uma horrível prática. Me recordam intruções JMP em assembly.
  • Fazer referência (através da intruções require ou include) à outros scripts (módulos ou classes) dentro de testes unitários que não estão na mesma pasta do artefato em teste é uma brincadeira de mau gosto.
  • Variáveis de instância para classes (além das variáveis de instância para instâncias e variáveis de classe para classes). Isso é realmente necessário?
  • Redefinição de visibilidade dentro de uma herança … aff Meu Deus!!!!

Conclusões : Ruby é uma linguagem poderosa e bastante flexível. Mas é preciso ter bom senso, porque você tem o poder de escrever códigos extrememante simples e funcionais, mas também possui a capacidade de criar coisas horríveis, como gatos que voam ou qualquer outra coisa bizarra …

[sourcecode language='cpp']

Deixe um comentário

Arquivado em Ruby

Do que gostei em ruby …

  • Metaprogramação
  • Redefinição de operadores
  • Cláusula else para tratamento de erros
  • Closures\Proc objects
  • Modificadores de expressões
  • Mixins
  • Ranges em expressões condicionais
  • O bloco case é interessante pelas cláusulas WHEN suportarem expressões não constantes
  • Em loops achei muito interessante as keywords retry e redo.
  • O nome de métodos podem ser acompanhados de ?, ! e =. Oferece mais readability. Ex:
    class ContaAPagar
    def quitada?
         return true
    end
    end
    
  • Alias
  • A palavra chave super atuando de forma contextual (isso é problemático às vezes)
  • Declarações de atributos (que não são palavras chaves e sim métodos da classe Module)
  • Duck Typing: O Tipo do objeto é determinado pelo o que ele pode fazer, não pela sua classe. Isso é legal, coerente. Mas exige bom senso e maturidade combinado com boas práticas, tipo testes unitários. Eu vejo que é muito improvável escrever um código com um estilo tão livre (laissez faire programming), em algum momento vc acaba usando o operador ===ou enviando a mensagem respond_to? à algun objeto.
  • O conceito de classes abertas
  • Definições de classe são blocos de código executável em runtime. Isso parece C\C++ com as diretivas #ifndef e #endif. A grande diferença é que essa análise em C\C++ em feita em tempo de compilação, em ruby é em runtime
  • Objetos congelados
  • Níveis de segurança e o conceito de Tainted Objects
Metaprogramação

Deixe um comentário

Arquivado em Ruby

Diminuindo a impaciência com XNA

Ultimamente venho lendo muitos livros e artigos sobre computação gráfica, física, algoritmos, OpenGL, álgebra linear e cálculo para aprimorar meu TCC e meu gosto pessoal por computação gráfica. Não é por nada não, mas me dá uma baita impaciência durante todo esse longo processo de abstração conceitual e não ter nada de prático, concreto – código – para fazer.

Resolvi então aplicar o que ia aprendendo em código: Durante minhas revisões sobre manipulação de matrizes e vetores, ao invés de ficar tomando notas do que lia resolvi escrever algumas operações como soma, subtração, produto, inversa e determinantes de matrizes quadradas ( utilizando cofatores ) em ruby e aprender ao mesmo tempo sobre o framework de testes unitários da linguagem confirmando alguns teoremas, tipo: “A transposta da transposta de uma matriz é ela mesma, o determinante de uma matriz e de sua transposta são iguais”.

Para saciar minha sede por aplicações, resolvi procurar por alguma ferramenta bem rápida para desenvolvimento de Games. Já tinha visto a Unity mas escolhi a plataforma XNA da Microsoft, embora a primeira tenha um ambiente de desenvolvimento muito bom também, seja compatível com várias linguagens e seja capaz de gerar uma versão do seu game para WEB. Já no XNA, achei interessante a forma como as particularidades do DirectX são encapsuladas e abstraídas. Você pode desenvolver com C# desde ridículas animações de sprites que eu venho fazendo (pacência, ainda estou terminando a parte de games 2D do livro Learning XNA 3.0)  até jogos 3D com qualidade de profissional.

Outra coisa massa do XNA é a versão à lá Microsoft do lema da plataforma Java: Write once, run anywhere. Desenvolvendo em XNA, você desenvolve para a plataforma .NET. Por consequencia, qualquer dispositivo que for .NET enabled está apto a executar seu código: Xbox 360. Resumindo você desenvolve em C# no seu PC e com mínimas alterações (tipo, um game no PC utiliza mouse e teclado, um Xbox 360 não tem mouse) você envia para seu Xbox seu game facilmente. Além disso, como um desenvolvedor solitário, você tem a oportunidade de vender seus games na rede Xbox live onde milhares de Xboxers competem e ganhar dinheiro fazendo o que gosta. Escolhi então XNA para saciar minha impacência.

Deixe um comentário

Arquivado em Computação Gráfica, Games, TCC, Xbox 360, XNA

Representação e persistência de valores monetários em Groovy com o padrão Money

Grande parte das aplicações comerciais manipulam valores monetários. Uma venda aqui, um estorno ali, um troco acolá, um parcelamento de um valor não inteiro … Todos esses movimentos devem ser devidamente registrados de forma precisa, pois aparentemente 0.01 R$ pode não fazer diferença para a farmácia da esquina da rua de sua casa, mas imagina isso acontecendo entre as centenas de movimentos de uma distribuidora internacional de medicamentos que cria parcerias e colaboradores por todo o mundo.

Implemente um pequeno sistema de PDV em Java ou qualquer outra linguagem e esteja disposto a encarar as mais inemagináveis lógicas, possibilidades e restrinções …. entre elas:

Um cliente informa os ítens que deseja levar e solicita o fechamento da venda. O funcionário solicita seu nome e procura um bônus de crédito acumulado, para um desconto no movimento. O sistema informa que o cliente tem 7.55 % de desconto acumulado para o próximo movimento. E ele possui um descontinho de 2.45 % por ter mais de 99 anos . Somando aí, temos 10 % de desconto. Bem, somando os ítens do cliente o sistema chega ao valor de 170 R$ e o sistema solicita ao cliente a forma de pagamento, que escolhe em 7 vezes. Fazendo umas continhas tirando o desconto do valor final fica em 153 R$ … dividindo isso em 7 parcelas nós temos 7x de 21,857142857142857142857142857143 … R$

O valor dessa parcela é válida ?? Existe essa quantia monetária em Reais ?? Como fazer: aproximar para 21.85 R$, (sendo que 7 parcelas 21.85 R$ totalizam   152,95 R$ e o caixa da loja perderá 5 cents ) ???

Eu tambem me deparei com essa situação e resolvi escutar a experiência da comunidade, encontrando o padrão Money. Antes vale destacar os livros e sites que fundamentaram essa implementação:

Assim como minhas necessidades quanto à implementação:

  • Preciso de operações de soma e subtração entre valores monetários
  • Preciso de operações de multiplicação e divisão entre valores monetários e escalares ( você não multiplica 10 R$ por 20 R$, multiplica ?)
  • Preciso persistir esse valor
  • Por enquanto, só trabalho com moeda brasileira, sem conversões e internacionalização

E para não ser um artigo inútil a você – caro leitor, e para a WEB, apresento-lhes um comentário sucinto da seguinte implementação da classe Money em groovy:

package br.netsoft

import org.hibernate.*;
import org.hibernate.usertype.*;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Locale;
import java.util.Properties;

import org.hibernate.usertype.UserType;
import java.sql.Types;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.*;
import java.io.Serializable;

/**
 *
 *  Implementação do padrão Money. Um Value Object
 *  Esta classe deve ser usada p/ implementar todos os valores monetários do sistema
 *  
 *  @author Lucas Simao
 *  @since 28/09/09
 *
 */
class Money implements UserType,Comparable<Money>,Serializable{

    private final static int CENT_FATOR = 100
    private static final Locale BR_LOCALE = new Locale('pt','BR');
    private static final DecimalFormat moneyFormat = new DecimalFormat('¤ ###,###,##0.00',new DecimalFormatSymbols(BR_LOCALE));
    long quantia // em centavos
    private Class targetClass;
    public final static Money ZERO = Money.newMoneyFromCents(0)



    /**
     *   Cria um novo valor monetário, à partir da quantia informada em <b> Centavos (R$) </b>.
     *   Exemplo:
     *
     *   <code>
     *      def m1 = Money.newMoneyFromCents(100) cria 1 real
     *   </code>
     *
     *   @since 28/09/09
     *   @param cents  O valor monetario, em centavos.
     *   @author Lucas Simao
     *
    */
    public static Money newMoneyFromCents(long cents){
        return new Money(quantia:cents)
        
    }

    /**
     *   Cria um novo valor monetário, à partir da quantia informada em <b> Reais (R$) </b>.
     *   Exemplo:
     *
     *   <code>
     *      def m1 = Money.newMoneyFromReal(100) // cria 100 Reais
     *      def m2 = Money.newMoneyFromCents(100) cria 1 real
     *   </code>
     *
     *   @since 28/09/09
     *   @param quantiaEmReais  O valor monetario, em reais.
     *   @author Lucas Simao
     *
    */
    public static Money newMoneyFromReal(double quantiaEmReais) {
        return new Money(quantia:quantiaEmReais * CENT_FATOR)
    }


    def getValorEmReais(){
        return this.quantia/100.0;
    }

    def getValorEmCentavos(){
        return this.quantia;
    }

    def plus(Money other){
        return adicionar(other)
    }

    public int compareTo(Object o){
        Money other = (Money)o
        return (this.quantia - other.quantia)
    }

    def minus(Money other){
        return subtrair(other)
    }

    def multiply(Double value){
        def valor_em_reais = this.quantia/100.0
        return Money.newMoneyFromReal(valor_em_reais*value)
    }

    public Money adicionar(Money qtde){
        return new Money(quantia: (qtde.quantia+this.quantia))

    }
    
    public Money subtrair(Money qtde){
        if (this.quantia<qtde.quantia){
            throw new IllegalStateException('Quantidade a ser subtraída maior que a quantia')
        }
        else{
            return new Money(quantia: (this.quantia-qtde.quantia))
        }}

  

    public List<Money> alocar(int n){
        
        long value = this.quantia/n
        Money lowResult = newMoneyFromCents(value);
        Money highResult = newMoneyFromCents(lowResult.quantia + 1);
        def results = [] as List
        int remainder = this.quantia % n;
        for (int i = 0; i < remainder; i++) results<< highResult;
        for (int i = remainder; i < n; i++) results << lowResult;
        return results;

    }

    public boolean equals(Money other){
        return (other.quantia == this.quantia)
    }

    public String toString(){
        return moneyFormat.format(this.getValorEmReais())
    }


    


    public boolean isMutable() { return false; }

    public Object deepCopy(Object value) { return value; }

    public Serializable disassemble(Object value){ return (Serializable) value; }
    
    public Object assemble(Serializable cached, Object owner) { return cached; }

    public Object replace(Object original, Object target, Object owner) { return original; }

    public boolean equals(Object x, Object y) { if (x == y) return true; if (x == null || y == null) return false; return x.equals(y); }


    public int hashCode(Object x) { return x.hashCode(); }

    // Cria um objeto Money à partir da quantia em centavos armazenada no BD
    public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws SQLException {
        Long value = resultSet.getLong(names[0]);
        if (value){
            return Money.newMoneyFromCents(value)
        }
        else{
            return Money.newMoneyFromCents(0L)
        }
    }

    // Salva o objeto Money representado pelo parâmetro value
    // como o valor em centavos
    public void nullSafeSet(PreparedStatement statement, Object value, int index) throws HibernateException, SQLException
    {
        if (value == null)
        {
            statement.setNull(index, Hibernate.LONG.sqlType());
        }
        else
        {
            statement.setLong(index, value.getValorEmCentavos());
        }
    }

        public void setParameterValues(Properties parameters) {
        String targetClassName = parameters.getProperty("targetClass");
        try { targetClass = Class.forName(targetClassName); }
        catch (ClassNotFoundException e)
        { throw new HibernateException("Class " + targetClassName + " not found ", e); } }

    public Class returnedClass() { return targetClass; }
    def SQL_TYPES = [Hibernate.LONG.sqlType()];

    public int[] sqlTypes() { return SQL_TYPES; } 
}

Sobre a classe Money:

  • Internamente, a quantia monetária é armazenada em centavos (propriedade quantia)
  • A classe implementa org.hibernate.usertype.UserType para definir um tipo de dados personalizado, no caso valores monetários. Os métodos  assemble, deepCopy, desassemble, equals, hashCode, isMutable, nullSafeGet, nullSafeSet, replace, returnedClass, sqlTypes são todos especificados por aquela interface e por isso implementados pela classe Money
  • Esta classe assume valores em reais. Por isso a ausência de alguma menção ao tipo de moeda
  • Ela é baseada no padrão Quantity, que encapsula e associa uma quantia com alguma unidade. Este por sua vez (quantity) deriva do padão Value Object
  • Existem dois métodos que dão vida a esta classe: newMoneyFromCents e newMoneyFromReal
  • Funcionalidades a serem implementadas: Internacionalização e conversão
  • Como groovy é uma linguagem dinâmica e permite sobrecarga de operadores, os métodos plus, minus, multiply e compareTo permite que você manipule facilmente instâncias de Money tornando válido o seguinte código:
def m1 = Money.newMoneyFromCents(100)
def m2 = Money.newMoneyFromReal(10.50)
def m3 = m1 + m2
println m3.toString() // imprime R$ 11.50
println m3 * 2 // imprime R$ 23.00

// resolvendo o problema descrito no início deste post

def m4 = Money.newMoneyFromReal(153.0)

// O método alocar irá retornar um array de tamnho 7, contendo 5 parcelas de
// R$ 21.86 e 2 de R$ 21.85, totalizando R$ 153.00

m4.alocar(7).each{ parcela -> println parcela }

Resumo da ópera: Implementado o padrão Money em Groovy, ao mesmo tempo, definindo um novo tipo de dados através da API org.hibernate.usertype do Hibernate.

Utilizando a classe Money com o Framework Grails

Simplesmente, redefina sua propriedade que armazena valores monetários ( que possivelmente esteja usando a classe Double ou BigDecimal ) para  o  tipo Money, além disso, informe ao Grails através da DSL de mapeamento que o tipo de dado Money é definido através das API’s do Hibernate, assim:

class Produto {
Money valorVenda
 static mapping = {
columns{
valorVenda type:Money
}
}
}

Patterns of Enterprise Application Architecture

3 Comentários

Arquivado em Grails, Groovy, Hibernate