LoginSignup
0

More than 5 years have passed since last update.

ジューコフスキー翼の座標を出す関数&plotlyで2D描画 & Three.jsで3D描画

Last updated at Posted at 2018-02-25

ジューコフスキー翼

ジューコフスキー翼というのを使えばそれっぽい翼型を描けます。とりあえずなんでもいいから翼を描きたいという方はお試しください。

参考URL FNの高校物理
http://fnorio.com/0116two_dimensional_wing_theory0/two_dimensional_wing_theory0.html

Imgur

座標を出す関数

下のzukofsky関数の3つの引数x0, y0, cに数字を入れると翼型を書くための関数zetaが返ってきます。zetaに0~2πの値を入れると翼面上の座標がx,yを含んだオブジェクトで帰ってきます。
x0で翼の太さ、y0で翼の反り具合、cで翼の長さを変えられます。

const zukofsky = (x0, y0, c) => {

  const b = c/4 
  const a = Math.sqrt((b-x0)**2+y0**2)

  const z = t =>{
    return {
      x: a*Math.cos(t)+x0,
      y: a*Math.sin(t)+y0,
    }
  }

  const invZ = t =>{
    const w = (a*Math.cos(t)+x0)**2+(a*Math.sin(t)+y0)**2
    return {
      x: (a*Math.cos(t)+x0)/w, 
      y: -(a*Math.sin(t)+y0)/w, 
    }
  }

  const zeta = t => {
    const temp1 = z(t)
    const temp2 = invZ(t)
    const temp3 = {x: 0, y:0}
    temp3.x = temp1.x + b**2*temp2.x
    temp3.y = temp1.y + b**2*temp2.y
    return temp3 
  }
  return zeta
}

const x0 = -0.05
const y0 = 0.1
const c = 1
const wing1 = zukofsky(x0, y0, c)

plotlyで2D描画

plotly.jsを使って、素直に描画します。翼面上の点を100分割します。

const N = 100 
const xyList = [...Array(N)].map((k,i)=>i).reduce((pre,i)=>{
  const temp = wing1(i*2*Math.PI/N)
  pre.x.push(temp.x)
  pre.y.push(temp.y)
  return pre 
},{x:[], y:[]})

const trace1 = {
  x: xyList.x,
  y: xyList.y,
  type: "scatter",
  model: "lines" 
}

const data = [trace1]
const layout = {
 height: 500, 
 width: 500, 
 xaxis:{
   range: [-0.6, 0.6]
 },
 yaxis:{
   range: [-0.6, 0.6]
 },
}
Plotly.newPlot("draw",data,layout,{
     editable: true,
    scrollZoom: true,
    showLink: false,
    displaylogo: false,
    modeBarButtonsToRemove: ['sendDataToCloud']
})

Threeで3D描画

THREE.ParametricGeometryがちょうどいいです。これは2つの変数u,vをパラメータにして面を描いてくれる関数です。ジューコフスキー翼は翼型を描くのにuを割り当てて、高さ方向の変化にvを割り当てると、高さ方向に形の異なる3Dの翼を描くことができます。

Imgur

var width = 500;
var height =500;

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45,width/height, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(new THREE.Color("rgb(0,0,0)"));
renderer.setSize(width, height);

var controls =  new THREE.OrbitControls( camera );
var axes = new THREE.AxesHelper(20);
scene.add(axes);

const x0 = -0.05
const y0 = 0.1
const c = 1 

const zukofsky = (x0, y0, c) => {

  const b = c/4 
  const a = Math.sqrt((b-x0)**2+y0**2)

  const z = t =>{
    return {
      x: a*Math.cos(t)+x0,
      y: a*Math.sin(t)+y0,
    }
  }

  const invZ = t =>{
    const w = (a*Math.cos(t)+x0)**2+(a*Math.sin(t)+y0)**2
    return {
      x: (a*Math.cos(t)+x0)/w, 
      y: -(a*Math.sin(t)+y0)/w, 
    }
  }

  const zeta = t => {
    const temp1 = z(t)
    const temp2 = invZ(t)
    const temp3 = {x: 0, y:0}
    temp3.x = temp1.x + b**2*temp2.x
    temp3.y = temp1.y + b**2*temp2.y
    return temp3 
  }
  return zeta
}

const wing1 = zukofsky(x0,y0,c)
const wingGeom1 = (u,v)=>{
  const A = 50
  const temp = wing1(u*2*Math.PI) 
  const x = temp.x*A 
  const y = temp.y*A 
  const z = v*A*2
  return new THREE.Vector3(x,y,z)
}

const createMesh = geometry => {
  const meshMaterial = new THREE.MeshNormalMaterial();
  meshMaterial.side = THREE.DoubleSide;
  const wireFrameMat = new THREE.MeshBasicMaterial();
  wireFrameMat.wireframe = true;
  const plane = THREE.SceneUtils.createMultiMaterialObject(
    geometry, [meshMaterial ,wireFrameMat])
  return plane
} 

const wing = createMesh(new THREE.ParametricGeometry(wingGeom1,50,50,false))
scene.add(wing);

camera.position.x = 100;
camera.position.y = 100;
camera.position.z = 100;


function animate() {
  requestAnimationFrame( animate );
  renderer.render( scene, camera );
  controls.update();
}

document.getElementById("draw")
  .appendChild(renderer.domElement);


animate();

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0