이벤트

Map

event module note
postcompose module:ol/render/Event~RenderEvent  
postrender module:ol/MapEvent~MapEvent Triggered after a map frame is rendered.
precompose module:ol/render/Event~RenderEvent  

PluggableMap

event module note
postcompose module:ol/render/Event~RenderEvent  
postrender module:ol/MapEvent~MapEvent Triggered after a map frame is rendered.
precompose module:ol/render/Event~RenderEvent  
rendercomplete module:ol/render/Event~RenderEvent Triggered when rendering is complete, i.e. all sources and tiles have finished loading for the current viewport, and all tiles are faded in.

WebGLMap

event module note
postcompose module:ol/render/Event~RenderEvent  
postrender module:ol/MapEvent~MapEvent Triggered after a map frame is rendered.
precompose module:ol/render/Event~RenderEvent  

Layer

event module note
postcompose module:ol/render/Event~RenderEvent  
render module:ol/MapEvent~MapEvent  
precompose module:ol/render/Event~RenderEvent  
rendercomplete module:ol/render/Event~RenderEvent Triggered when rendering is complete, i.e. all sources and tiles have finished loading for the current viewport, and all tiles are faded in.

ImageLayer

event module note
postcompose module:ol/render/Event~RenderEvent  
ender module:ol/MapEvent~MapEvent  
precompose module:ol/render/Event~RenderEvent  
rendercomplete module:ol/render/Event~RenderEvent Triggered when rendering is complete, i.e. all sources and tiles have finished loading for the current viewport, and all tiles are faded in.

Heatmap

event module note
postcompose module:ol/render/Event~RenderEvent  
render module:ol/MapEvent~MapEvent  
precompose module:ol/render/Event~RenderEvent  
rendercomplete module:ol/render/Event~RenderEvent Triggered when rendering is complete, i.e. all sources and tiles have finished loading for the current viewport, and all tiles are faded in.

정리

위 이벤트들의 작동을 확인하기 위해 Openlayers render event라는 예제 페이지를 작성하여 확인하였다.

  • Mapprecompose가 발생 이후, Layer들의 사이클이 돈 이후, postcompose, postrender 발생
  • 하나의 Layer가 사이클이 돌 땐, precompose ~ postcompose의 일련의 과정이 발생하고 다음 Layer로 이동
  • 타일 Layer는 불리는 대로 일련의 과정이 발생하고, precompose, postcompose만 발생
  • VectorLayerprecompose, render, postcompose가 발생
  • VectorLayerstyle functionprecompose 전에 실행
  • VectorLayerstyle function은 갱신의 필요가 없을 경우 발생하지 않음(미세하게 지도가 움직이거나 새로운 레이어가 추가되었을 경우)
  • Layerrendercomplete가 발생하는 경우는 확인하지 못했으며, Maprendercomplete는 최초 로드 시를 제외하고 가장 마지막 postrender 이후 발생

Coding The Matrix를 보면서 벡터의 생성, 선형결합, 벡터공간, 아핀공간의 정의에 대해 자주 잊어버려 읽을 때 참고하고자 이를 정리하고자 한다.


  • 생성의 정의(Definition 4.2.1)

벡터들 $v_1, …, v_n$의 모든 선형결합으로 이루어진 집합을 이 벡터들의 생성이라하고 $Span {v_1, …, v_n}$라고 쓴다.


이 정의를 이해하기 위해서는 선형결합이 무엇인지 먼저 알아야한다.


  • 선형결합의 정의(Definition 4.1.1)

$v_1, …, v_n$ 각각을 벡터라고 하자. $v_1, …, v_n$의 선형결합을 다음과 같은 합이라고 정의하자.

여기서, $\alpha_1, …, \alpha_n$은 스칼라이다. 이 선형결합에서 $\alpha_1, …, \alpha_n$ 각각은 계수라고 한다. $\alpha_1$은 $v_1$의 계수이고, $\alpha_2$은 $v_2$의 계수이며, …, $\alpha_n$은 $v_n$ 의 계수이다.


문득 궁금했던 것이 생성은 영벡터를 항상 포함하는지 궁금하였다. 생성은 벡터들 $v_1, …, v_n$의 모든 선형결합으로 이루어진 집합이기 떄문에 영벡터를 항상 포함할 것으로 생각된다.

아래와 같이 $GF(2)$상의 $Span {[1, 1], [0, 1]}$에 있는 벡터를 살펴보면,

생성의 4개의 벡터가 있음을 볼 수 있는데, 선형결합의 $\alpha_1, …, \alpha_n$ 계수가 모두 0인 경우에 영벡터를 포함하게된다. $\alpha_1, …, \alpha_n$ 계수의 범위를 한정 지어주거나, 평행이동을 하지 않는 이상 생성에는 영벡터가 포함되는 것이 아닐까한다.


  • 벡터공간의 정의(Definition 4.4.1)

벡터들의 집합 V가 Property V1, V2, V3를 만족하면, 벡터공간이라고 한다.

  • Property V1: $V$는 영벡터를 포함한다.
  • Property V2: 모든 벡터 $v$에 대해, 만약 $V$가 $v$를 포함하면 $V$는 모든 스칼라 $\alpha$에 대해 $\alpha v$를 포함하고 스칼라-벡터 곱에 대해 닫혀 있다.
  • Property V3: 모든 벡터들의 쌍 $u$, $v$에 대해, 만약 $V$가 $u$, $v$를 포함하면 $V$는 $u + v$를 포함한다.

어떤 벡터들의 생성과 동차 선형 시스템의 해집합은 벡터공간이다. 두 경우 모드 영벡터를 포함하고 덧셈, 곱셈에 닫혀있다.


  • 아핀공간의 정의(Definition 4.5.8)

아핀공간은 벡터공간을 평행이동한 결과이다. 즉, 집합 $A$는 다음을 만족하는 벡터 $a$와 벡터공간 $V$가 있으면 아핀공간이다.

즉 $A = a + v$이다.


원점을 지나지 않는 직선에 대해서 어떻게 생성으로 표현할 것인가에 대해 궁금하였었는데, 벡터공간을 평행이동한 아핀공간을 통하여 표현하면 된다.

Coding The Matrix 4장(원서 3장) 벡터공간에서 원점을 포함하는 flat의 다음 두 가지 표현에 대해 설명한다.

  • 어떤 벡터들의 생성으로서
  • 동차 선형시스템의 해집합으로서

이 글에서 작성하고자 하는 내용은 이 표현들의 설명은 아니다. 단지, 책에서 이 두가지 표현에 대한 예제가 나오는데 해당 예제에 대해서 스터디에서 많은 의견이 오고가서 이에 대해 정리하고자 한다. 두 예제는 아래와 같다.


  • Example 4.3.7

평면

은 다음과 같이

우변이 영인 선형방적식의 해집합으로 나타낼 수 있다.


  • Example 4.3.10

직선

은 다음과 같이

두 동차 선형방정식 쌍들의 해집합으로 나타낼 수 있다.


Example 4.3.7의 도출은 $ax+bx+cz=0$에 대입하여 연립방정식을 정리하면 쉽게 도출할 수 있었다. 하지만, Example 4.3.10의 경우는 저 두 평면이 교차하는 직선(두 동차 선형방정식의 해집합)이 생성과 동일하다는 것만 이해되고 어떠한 기준에서 두 동차 선형방정식이 도출된 것인지 알 수 없었다.

우선 Example 4.3.7의 경우, 생성과 해집합 모두 깔끔하게 아래와 같은 평면으로 표현할 수 있어서 이해하기 쉬웠다.

Example 4.3.10의 경우에도 각각 생성과 해집합이 아래와 같은 두 평면이 교차하는 직선인 것은 쉽게 이해할 수 있었다.

계속 의문을 가졌던 것은 위 생성에서 어떻게 두 동차 선형방정식을 도출할 수 있을까였다. 계속 이런 저런 이야기를 하다보니, 평면이 교차해서 생기는 직선은 무수히 많을 수 있다는 것을 간과하고 있다는 것을 Ro달았다. 예제에서 든 두 동차 선형방정식 외에도 얼마든지 다른 방정식의 쌍을 예로 들어도 되었을 것이다.

덧붙여서 이와 관련된 검색을 하던 도중에 흥미로운 StackExchange에 올라온 How to turn span into linear equality constraint?글의 질문과 답변을 보았다.

필자는 Example 4.3.7를 도출하기 위해 $ax+bx+cz=0$에 대입하여 연립방정식으로 정리하였는데, 위 질문에서는 이를 행렬로 정리하는 것을 보았다.

$e_1=\begin{bmatrix}1\\0\\1.65\end{bmatrix}$ 와 $e_2=\begin{bmatrix}0\\1\\1\end{bmatrix}$ 의 생성에 놓여있는 $u=\begin{bmatrix}x\\y\\z\end{bmatrix}$ 는 $u=\lambda e_1+\mu e_2$를 만족할 것이다.

이때 아래와 같이 가우스 정리를 통해 정리하면,

마지막 행의 마지막 요소인 $z-1.65x-y$은 우변인 $0$을 만족하여야한다.

위와 같이 가우스 소거법을 사용하여 정리하면 좀 더 계산하기 쉽게 동차 선형방정식을 도출할 수 있다. 특히 Example 4.3.7와 달리 더 높은 차원에서 동차 선형방정식을 구해야할 경우에 유용할 것 같다.

let sub: Subscription = this.http.get(url).subscribe(()=>{});

HttpClient를 사용하여 구독하고 난뒤에 해지가 필요한가 궁금했다.

mousemove와 같은 DOM 이벤트는 구독 후 필수로 해지해 주고 있었지만 HttpClient를 사용한 후에는 알아서 구독을 종료해 준다고 하여서 따로 unsubscribe()를 하지는 않았다.

한편으로는 눈으로 직접 본 것이 아니어서 늘 마음한 구석이 찝찝하여, Angular 내 해당 부분을 찾아보았다.

export class XHRConnection implements Connection {
  // ...
      const response = new Response(responseOptions);
      response.ok = isSuccess(status);
      if (response.ok) {
        responseObserver.next(response);
        // TODO(gdi2290): defer complete if array buffer until done
        responseObserver.complete();
        return;
      }
      responseObserver.error(response);
  // ...
}

angular/packages/http/src/backends/xhr_backend.ts를 살펴보면, response.ok인 경우에 next를 호출 후 compelete를 호출하여 종료함을 확인할 수 있다.

RxJS에서 API 호출 실패 시 300초 간격으로 3회를 재시도하는 로직을 작성하고 싶어서 찾아보니, 아래와 같이 작성하면 원하는 대로 작동하였다.

retryWhen((errors: any) => {
  return concat(
    errors.pipe(
      delay(300),
      take(3),
    ),
    throwError()
  );
}),

하지만 상단의 코드와 같이 작성하였더니, 마지막에 발생한 에러에 대한 정보를 받고자 했지만 받을 방법이 없었다.

그래서 아래와 같이 tap을 사용하여 에러가 발생할 때 마다 error에 대한 정보를 저장하고 마지막에 그 객체를 전달하는 방식으로 처리하였다.

retryWhen((errors: any) => {
  const error = {};
  return concat(
    errors.pipe(
      delay(300),
      tap((err: any) => Object.assign(error, err)),
      take(3),
    ),
    throwError(error)
  );
}),