모니터를 듀얼로 사용하고 하나가 더 있으면 좋을것 같을때 핸드폰이나 타블렛을 이용하여 보조 모니터로 사용하는 방법입니다무선으로 작동하고 무료로 사용이 가능 합니다.

 

작업방법은

1. PC, 노트북 프로그램 다운로드 설치

2. 모바일 기기 프로그램 다운로드 설치

3. 연결 확인

 

프로그램설치 과정 때문에 글이 길어지는데 실제 설정은 상당히 간단합니다.

 


1. 데스크 탑, 노트북에 프로그램 설치

 

1.1 프로그램 다운로드


사이트에 접속헤서 프로그램을 다운로드 해야 합니다.


https://www.spacedesk.net/


Windows 7, 8, 10을 지원하며 자신의 운영체제에 맞는 파일을 찾아 다운로드 하면 됩니다.


spacedesk_mobile_monitor


1.2 프로그램 설치

 

다운받은 파일을 실행 하여 설치 합니다.

 

spacedesk_driver_Win_7_64_v0914_BETA.msi

 

설치는 그냥 Next를 클릭 하면 됩니다.


spacedesk_mobile_monitor

spacedesk_mobile_monitor

spacedesk_mobile_monitor


여기에서 한번 라이센스 확인을 해주고 Next 버튼을 클릭 합니다.


spacedesk_mobile_monitor

spacedesk_mobile_monitor

spacedesk_mobile_monitor


여기서 부터 마우스, 키보드, 디스플레이를 모바일 디바이스와 연결하기 위해 설치를 진행 하는데 모두 설치 버튼을 클릭해 줍니다.


spacedesk_mobile_monitor

spacedesk_mobile_monitor

spacedesk_mobile_monitor

spacedesk_mobile_monitor


설치가 완료되면 윈도우를 재시작 하여 운영체제에 반영을 시킵니다.


1.3 설정

 

윈도우즈 우측 하단 숨겨진 아이콘 표시에 들어가면 모니터 모양의 아이콘이 있습니다그걸 클릭하면 spacedesk 팝업 창이 나타납니다.


spacedesk_mobile_monitor




spacedesk_mobile_monitor


중간에 IP Address가 보이는데 이 번호를 이용하여 핸드폰, 타블렛이 접속할 수 있습니다디스플레이 설정은 가운데 ... 아이콘을 클릭해서 설정 합니다.


spacedesk_mobile_monitor


아래 화면은 핸드폰이나 타블렛을 연결 한 후에 볼 수 있는 화면입니다보조 모니터를 연결 해야 다중모니터가 잡혀서 설정이 가능 합니다현재는 디스플레이 복제를 하였습니다.


spacedesk_mobile_monitor



2. 모바일 기기 프로그램 다운로드 설치

 

2.1 프로그램 다운로드

 

Play스토어에서 spacedesk를 검색하여 설치를 하고 설치 후 열기를 합니다.

 


spacedesk_mobile_monitor


앱이 실행되면 가운데 + 아이콘을 클릭하고 서버에 있는 IP 번호를 입력한 후 ADD를 클릭 합니다.


spacedesk_mobile_monitor


이제 서버가 하나 추가 되었습니다서버를 클릭해 주면 바로 접속이 됩니다.


spacedesk_mobile_monitor



3. 연결 확인

 

사진을 찍으려 디스플레이 복제를 선택 했습니다. 확장등을 사용해서 테스트 해보시기 바랍니다다른것 보다 무선이라 마음에 듭니다.


spacedesk_mobile_monitor


노트북에서 5m정도 떨어지니 버퍼링이 발생하기 시작 하는군요. 5미터나 떨어져서 작업할 일은 없으니 공짜치고는 좋은듯 합니다.


 

2. 데이터 형, 변수

 

2.1 숫자형

 

2.1.1 Integer


Python에서 int 일반적으로 알고 있는 정수로 사용되지 않습니다.  int란 소숫점 이하의 값이 없음을 말하는 것이 아니라 소숫점 자체가 존재 하지 않는 뜻 입니다또한 파이썬에는 long형의 자료형이 존재 하지 않고 int로 값을 표현 합니다.

소숫점 이하의 값은 버림을 하고 조건을 int 로 변경할 수 있습니다.

 

print(type(1), type(1000000), type(9999999999999999999999999999999999999999999999), sep='/')
print(int(1), int(30.0), int(-34.5), int(7777777.9999999), sep='/')
print(int(1==1), int(1 < 0), int(True), int(False), sep='/')


 결과

 <class 'int'>/<class 'int'>/<class 'int'>

 1/30/-34/7777777

 1/0/1/0

 <class 'float'>/<class 'float'>/<class 'float'>/<class 'float'>/<class 'float'>


python study


2.1.2 Float


Python에서 float는 숫자에 소숫점이 존재 하는 경우를 말하며 소숫점 이하에 값이 있고 없고는 관계 없습니다.

int 형 값은 float형으로 변환 하고 조건 값도 float 형으로 변환 합니다.


print(type(3333.3333), type(0.0), type(2e-10), type(3.0), type(4.), sep='/')
print(float(1), float(30), float(-34), float(7777777), sep='/')
print(float(1==1), float(1 < 0), float(True), float(False), sep='/')


 결과

 <class 'float'>/<class 'float'>/<class 'float'>/<class 'float'>/<class 'float'>

 1.0/30.0/-34.0/7777777.0

 1.0/0.0/1.0/0.0

 

2.2 문자, 문자열(str)

 

파이썬에서 문자는 str로 정의 합니다.

 

print(type('a'), type('I am a boy!'), type('-34.5'), type('7777777.9999999'), sep='/')


 결과

 <class 'str'>/<class 'str'>/<class 'str'>/<class 'str'>

 

2.2.1 작은 따옴표


문자열을 작은 따옴표로 묶어서 표현합니다.


txt1 = '문자열을 작은 따옴표로 묶었습니다.'
print(txt1)
print('문자열을 작은 따옴표로 묶었습니다.')


 결과 

 문자열을 작은 따옴표로 묶었습니다.

 문자열을 작은 따옴표로 묶었습니다.

 

2.2.2 큰 따옴표


작은 따옴표와 동일하게 사용됩니다.

작은 따옴표도 포함해서 사용이 가능 합니다.


txt2 = "문자열 큰따옴표 안에  '작은' 따옴표가 있습니다."
print(txt2)
print("문자열 큰따옴표 안에  '작은' 따옴표가 있습니다."


 결과 

 문자열 큰따옴표 안에  '작은따옴표가 있습니다.

 문자열 큰따옴표 안에  '작은따옴표가 있습니다.


2.2.3 따옴표 세게 (“”” 또는 ‘’’)


긴 주석이 필요한 경우에 사용 합니다.

따옴표 세개로 묶은 문자열 안에서는 작은 따옴표와 큰 따옴표를 마음대로 사용할 수 있습니다.


"""
시작과 끝을 따옴표로 마크하여 아무 글이나 편안하게 써도 됩니다.
Its fine.
▒◀◁◆◈◎★☎☜〈》』】〔
ぁぇぉきけこさとずねづサシセラャヮ
★㎱㎳㎪薙蕞햰ÚÅöåⓙⓖが♧♥♣☎ボ㈅ㆃㆃ
"""

 

2.2.4 문자열 Format


format을 사용하여 문자열의 일부를 상황에 따라 다른 문자로 대체할 수 있습니다.

개인별 맞춤 메일, 공지, 안내, 경고 등에 사용 할 수 있습니다.

 

user_name = "홍길동"
user_name2 = "강감찬"
count = 10

print('{}회원님은 {}번째 로그인 하셨습니다.'.format(user_name, count))
print('{2}회원님은 {1}번째 로그인 하셨습니다'.format(user_name, count, user_name2))

 

 결과 

 홍길동회원님은 10번째 로그인 하셨습니다.

 강감찬회원님은 10번째 로그인 하셨습니다

 

2.2.5 특수 문자


특수 문자는 역슬래시(\)를 사용해서 입력 가능 합니다.

- 작은 따옴표, 큰 따옴표 하나를 입력 하는 경우 : \’, \”

- 역슬래시를 하나 입력하는 경우 : \\

- (tab)을 입력 하는 경우 : 시작\t

- 줄바꿈 하는 경우: \n (이 문장을 출력 하고\n다음줄에 이 문장이 나옵니다.)

- 문장 또는 명령어가 길 경우 이어 쓰기를 위해 끝에 추가 합니다   

print('- 작은 따옴표, 큰 따옴표 하나를 입력 하는 경우 : \', \"')
print('- 역슬래시를 하나 입력하는 경우 : \\')
print('- (tab)을 입력 하는 경우 : 시작\t')
print('- 줄바꿈 하는 경우: \n (이 문장을 출력 하고\n다음줄에 이 문장이 나옵니다.)')
txt3 =
'이 문장은 끝난게 아니고 \
여기 이 문장까지가 끝입니다.'
print(txt3)
sum1 =
3 + 3 \
       +
4 + 4
print(sum1)
txt4 =
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaa' \
     
'bbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
print(txt4)

 결과 

 작은 따옴표큰 따옴표 하나를 입력 하는 경우 : ', "

 - 역슬래시를 하나 입력하는 경우 : \

 - (tab)을 입력 하는 경우 : 시작  

 - 줄바꿈 하는 경우:

 (이 문장을 출력 하고

 다음줄에 이 문장이 나옵니다.)

 이 문장은 끝난게 아니고 여기 이 문장까지가 끝입니다.

 14

 aaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbb

 

 

2.3 변수

 

프로그램 중간에 값을 담아둘 수 있는 공간을 위한 변수를 만들 수 있습니다.

변수의 생성 규칙은

- 알파벳 대소문자, 대소문자를 사용 할 수 있으며 대소문자가 구분됩니다.

- 숫자(0~9)를 사용할 수 있습니다.

- 밑줄(_)문자를 사용할 수 있습니다.

- 변수의 시작 첫 문자는 알파벳이나 밑줄로 시작하며 숫자는 오류 발생합니다.

 

 aValue7 = 30
 AValue7 = 60
 _AValue7 = 90
 print(aValue7, AValue7, _AValue7, sep=',')


 결과

 30,60,90

 

 7AValue = 120

 

 결과 

 7AValue = 120

          ^

 SyntaxError: invalid syntax


- copy coding -


Python을 학습하기 위해 파이썬을 꼭 설치할 필요는 없습니다. 파이썬 사이트에서는 online console을 제공하여 웹브라우저에서 테스트가 가능합니다몇일전 ‘Python 기초학습 1’을 올리려고 할때 이 기능이 없어져서 삭제한줄 알았는데 오늘은 또 나타났습니다아마 버전업을 했거나 내부 작업이 있었던듯 하네요다시 수정해서 올리는데 또 사라지면 내가 거짓말쟁이가 되는데...


python_online_console

사용법은 노란색 네모 버튼을 클릭 하면 잠시후 콘솔 창으로 변합니다그럼 그곳에서 코딩을 하거나 다른곳에서 코딩하고 복사를 해도 됩니다.


python_online_console


python study

 

1. 기초


1.1 주석


- # 이후의 문장

- 예외 : 문자 인코딩

# 문자로 시작되는 문장은 주석으로 인식 합니다.

위치는 관계 없고 # 이후의 문장은 모두 주석으로 인식 됩니다.

a = 1
b = 2
c = a + b  # a 더하기 b의 값을 c에 저장 합니다.
#
여기에 기입된 문자는 주석 입니다.
print(c)


 결과

 3

 

 

1.2 인코딩


#으로 시작 되어도 프로그램 상단에 있는 인코딩은 주석이 아닙니다.

#-*- coding: utf-8 -*-

 

#-*- coding: euc-kr -*-

 

1.3 세미 콜론(;)


명령 행의 끝을 나타내기 위해 세미 콜론(;)을 사용하거나 하지 않거나 동일한 결과가 나옵니다.

print ('use semicolon test')
print ('use semicolon test');

 결과 

 use semicolon test

 use semicolon test

 

위의 명령은 동일한 결과가 나오지만 세미콜론 사용은 권장하지 않습니다.

세미 콜론을 이용하여 두개의 명령어를 연결해서 작업할 수도 있지만 이것도 권장하지 않습니다.

 

cnt = 10; print (cnt)

 결과 

 10


한 줄에 하나의 명령만 사용하길 권장하고 모두 그렇게 사용 하고 있어 세미콜론이 들어가면 다른 개발자에게 오히려 혼란을 줄 수 있습니다.

 

1.4 print


- print 명령으로 출력을 하면 자동 줄바꿈 됩니다.

print('문자 출력 테스트 하기')
print('문자 출력 ')
print('테스트 하기')

 결과 

 문자 출력 테스트 하기

 문자 출력

 테스트 하기


 

- 숫자, Boolean 등도 출력이 가능 합니다.


print(3, 3.333, 0.33333, 2e10, 2e-7)
print(3 + 2, 3.7 * 4, 3 < 4, False, True, 1 == 0)


 결과 

 3 3.333 0.33333 20000000000.0 2e-07

 5 14.8 True False True False

 

- 출력에 구분자를 넣어서 출력이 가능 합니다.

 

print(3, 3.333, 0.33333, 2e10, 2e-7, sep=',')
print(3 + 2, 3.7 * 4, 3 < 4, False, True, 1 == 0, sep='/')


 결과 

 3,3.333,0.33333,20000000000.0,2e-07

 5/14.8/True/False/True/False


문장의 끝을 변경 할 수 있습니다.

 

print('문자 출력 ', end='')
print('테스트 하기')

print('문자 출력 ', end=' 여기에 ')
print('테스트 하기')


 결과

 문자 출력 테스트 하기

 문자 출력  여기에 테스트 하기

 

1.5 들여쓰기


한줄로 명령이 종료되는 경우 다음 줄에 들여쓰기를 하면 오류가 발생 합니다.

조건문, 반복문 같이 다음에 명령이 종속되는 경우만 들여쓰기를 사용 합니다.


if(1==1):
   
print('1 = 1')
else:
   
print('! != 1')


 결과 

 1 = 1


- copy coding -


대략적인 개념이기 때문에 실제 사용할 수 있는 나침반을 만들려면 다른 변수들도 반영니 되야 겠지만 가속도 센서(TYPE_ACCELEROMETER)자기장 센서(TYPE_MAGNETIC_FIELD)를 이용하여 단순한compass를 만들어보겠습니다구현 방법은 구글에서 이미 함수를 만들어서 제공을 하기 때문에 그걸 그대로 사용합니다. 사용되는 함수는 getRotationMatrix() getOrientation() 입니다.



1. 함수

 

1.1 getRotationMatrix


 public static boolean getRotationMatrix (float[] R,

                float[] I,

                float[] gravity,

                float[] geomagnetic)


Type

 Parameter

 설명

 float[9]

 R

 회전 매트릭스 (Rotation matrix)

 float[9]

 I

 경사도 매트릭스 (Inclination matrix)

 float[3]

 gravity

 장치 좌표계의 gravity vector(TYPE_ACCELEROMETER)

 float[3]

 geomagnetic

 장치 좌표계의 geomagnetic vector(TYPE_MAGNETIC_FIELD)


getRotationMatrix()는 경사도와 회전 매트릭스를 구하는 함수로 지구에 대한 세계 좌표계(World Coordinate System)를 기준으로 핸드폰 장치의 좌표계의 변화하는 값을 구합니다세계 좌표계에서 서로 직교하는 3개의 축은

x : 지표면에 접하는 동쪽 방향의 벡터

y : 지표면에 접하는 북극 방향의 벡터

z : 지표면과 직각을 이루는 상공을 향하는 벡터

으로 설명 할 수 있습니다구글에서 설명하는 그림을 참고하면 아래와 같습니다.


android_compass


나침반을 만들 때에는 경사도 매트릭스를 사용하지 않습니다.


2.2 getOrientation


getOrientation() 함수는 rotation matrix를 이용하여 장치의 방향을 구하는 함수입니다. getRotationMatrix() 함수를 통해 구한 첫 번째 값인 회전 매트릭스를 사용해서 방향을 구할 수 있습니다.


public static float[] getOrientation (float[] R,

                float[] values)


Parameter

 설명

 R

 otation matrix : getRotationMatrix(float[], float[], float[], float[])

 values

 float[3] :

values[0]: Azimuth. z축에 대한 회전 방위각으로 이게 필요하죠.

values[1]: Pitch. x축에 대한 회전 방위각

values[2]: Roll. y축에 대한 회전 방위각


설명에도 기술 하였지만 getRotationMatrix()에서 회전 매트릭스 (Rotation matrix)를 구하여 getOrientation()에 입력하면 values[0] (Azimuth : z축에 대한 회전 방위각) 구하게 됩니다 값이 바로 북을 향하는 각도가 됩니다.

 

 

2. 프로젝트 생성

 

CompassTest 라는 이름으로 프로젝트를 생성 합니다.


android_compass


Activityempty로 선택합니다.


android_compass


나머지는 그냥 기본 설정 값으로 놓고 Next 버튼을 클릭 합니다.


3. 코딩

 

3.1 layout

 

구해진 회전각을 출력 할 수 있는 TextView를 하나 생성하고 나침반 이미지를 위해서 ImageView를 추가 합니다.


<TextView
    android:id="@+id/DegreeTV"
    android:layout_width="wrap_content"
    android:layout_height="18dp"
    android:layout_marginBottom="8dp"
    android:layout_marginTop="8dp"
    android:text="Heading : 0.0"
    app:layout_constraintBottom_toTopOf="@+id/pointer"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.027"
    tools:layout_editor_absoluteX="127dp" />

<ImageView
    android:id="@+id/pointer"
    android:layout_width="match_parent"
    android:layout_height="437dp"
    android:src="@drawable/compass_icon"
    tools:layout_editor_absoluteX="0dp"
    tools:layout_editor_absoluteY="56dp" />


이미지는 인터넷에서 무료 이미지를 하나 줏어왔습니다. 배경이 투명이 아니라 돌아갈때 커다란네모가 돌면서 글씨를 가리는 군요전에 작업한 투명이미지 만들기를 보면서 수정했습니다.


[Pixlr] Adobe Photoshop 없이 무료 투명 배경 이미지 만들기


android_compass


3.2 방위각 구하기


getRotationMatrix() 함수를 이용하여 회전 매트릭스(mR)를 구합니다.


SensorManager.getRotationMatrix(mR, null, mLastAccelerometer, mLastMagnetometer);


mR을 이용하여 getOrientation()에서 방위각을 구합니다.


SensorManager.getOrientation(mR, mOrientation);


3.3 이미지 회전


z 축의 회전각으로 RotateAnimation()을 이용하여 이미지를 회전 시킵니다.

RotateAnimation ra = new RotateAnimation(
mCurrentDegree,
-azimuthinDegress,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f
);

이미지 회전 설명은 [Android] 안드로이드 RotateAnimation 함수 이용 이미지 회전 을 참조 하세요.



3. 결과


android_compass


 

4. 전체 소스

 

activity_main.xml


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/DegreeTV"
        android:layout_width="wrap_content"
        android:layout_height="18dp"
        android:layout_marginBottom="8dp"
        android:layout_marginTop="8dp"
        android:text="Heading : 0.0"
        app:layout_constraintBottom_toTopOf="@+id/pointer"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.027"
        tools:layout_editor_absoluteX="127dp" />

    <ImageView
        android:id="@+id/pointer"
        android:layout_width="match_parent"
        android:layout_height="437dp"
        android:src="@drawable/compass_icon"
        tools:layout_editor_absoluteX="0dp"
        tools:layout_editor_absoluteY="56dp" />
</android.support.constraint.ConstraintLayout>


MainActivity.java


package copycoding.tistory.com.compasstest;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements SensorEventListener {

    private ImageView mPointer;
    private SensorManager mSensorManager;
    private Sensor mAccelerometer;
    private Sensor mMagnetometer;
    private float[] mLastAccelerometer = new float[3];
    private float[] mLastMagnetometer = new float[3];
    private boolean mLastAccelerometerSet = false;
    private boolean mLastMagnetometerSet = false;
    private float[] mR = new float[9];
    private float[] mOrientation = new float[3];
    private float mCurrentDegree = 0f;
    TextView DegreeTV;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        mPointer = (ImageView)findViewById(R.id.pointer);
        DegreeTV = (TextView)findViewById(R.id.DegreeTV);

    }

    @Override
    protected void onResume() {
        super.onResume();
        mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
        mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mSensorManager.unregisterListener(this, mAccelerometer);
        mSensorManager.unregisterListener(this, mMagnetometer);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if(event.sensor == mAccelerometer) {
            System.arraycopy(event.values, 0, mLastAccelerometer, 0, event.values.length);
            mLastAccelerometerSet = true;
        } else if(event.sensor == mMagnetometer) {
            System.arraycopy(event.values, 0, mLastMagnetometer, 0, event.values.length);
            mLastMagnetometerSet = true;
        }
        if(mLastAccelerometerSet && mLastMagnetometerSet) {
            SensorManager.getRotationMatrix(mR, null, mLastAccelerometer, mLastMagnetometer);
            float azimuthinDegress  = (int) ( Math.toDegrees( SensorManager.getOrientation( mR, mOrientation)[0] ) + 360 ) % 360;
            DegreeTV.setText("Heading : " + Float.toString(azimuthinDegress) + " degrees");
            RotateAnimation ra = new RotateAnimation(
                    mCurrentDegree,
                    -azimuthinDegress,
                    Animation.RELATIVE_TO_SELF, 0.5f,
                    Animation.RELATIVE_TO_SELF, 0.5f
            );
            ra.setDuration(250);
            ra.setFillAfter(true);
            mPointer.startAnimation(ra);
            mCurrentDegree = -azimuthinDegress;
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

}



1···87888990919293···118

+ Recent posts