-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
지도 기능 #455
지도 기능 #455
Changes from 32 commits
8f4c46a
5016eef
cb97af4
534098e
64bb3c8
cd4ea53
61472c8
80eae2e
ab2e217
d72d17b
219f1fa
5312ecd
48ba832
8a4773f
6c85817
80c755a
90f3c49
6673f30
e8da93b
0ffc535
aae9b15
fab67ef
7713312
cb5074f
29d4ea1
67520c2
e6774f5
a44ac82
93b795a
56188a5
eb52d23
d1d422e
7c42a01
c379a6c
4d014f2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.project.yozmcafe.controller; | ||
|
||
import java.util.List; | ||
|
||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import com.project.yozmcafe.controller.dto.cafe.CafeLocationRequest; | ||
import com.project.yozmcafe.controller.dto.cafe.CafeLocationResponse; | ||
import com.project.yozmcafe.service.LocationService; | ||
|
||
@RestController | ||
@RequestMapping("/cafes/location") | ||
public class LocationController { | ||
|
||
private final LocationService locationService; | ||
|
||
public LocationController(final LocationService locationService) { | ||
this.locationService = locationService; | ||
} | ||
|
||
@GetMapping | ||
public ResponseEntity<List<CafeLocationResponse>> findCafesFromLocation( | ||
final CafeLocationRequest cafeLocationRequest) { | ||
final List<CafeLocationResponse> cafesFromLocations = locationService.findCafesFromLocations( | ||
cafeLocationRequest); | ||
return ResponseEntity.ok(cafesFromLocations); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.project.yozmcafe.controller.dto.cafe; | ||
|
||
import org.locationtech.jts.geom.Point; | ||
|
||
import com.project.yozmcafe.domain.cafe.Cafe; | ||
import com.project.yozmcafe.domain.cafe.GeometryGenerator; | ||
import com.project.yozmcafe.domain.cafe.coordinate.CafeCoordinate; | ||
|
||
public record CafeCoordinateRequest(double latitude, double longitude) { | ||
|
||
public CafeCoordinate toCafeCoordinateWithCafe(final Cafe cafe) { | ||
final Point point = GeometryGenerator.generatePointWithCoordinate(latitude, longitude); | ||
return new CafeCoordinate(point, cafe); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package com.project.yozmcafe.controller.dto.cafe; | ||
|
||
public record CafeLocationRequest(double latitude, double longitude, double latitudeDelta, double longitudeDelta) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 파라미터 dto 굿~~ |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.project.yozmcafe.controller.dto.cafe; | ||
|
||
import com.project.yozmcafe.domain.cafe.coordinate.dto.CafePinDto; | ||
|
||
public record CafeLocationResponse(Long id, String name, String address, double latitude, double longitude) { | ||
|
||
public static CafeLocationResponse from(final CafePinDto cafePinDto) { | ||
return new CafeLocationResponse( | ||
cafePinDto.getId(), | ||
cafePinDto.getName(), | ||
cafePinDto.getAddress(), | ||
cafePinDto.getLatitude(), | ||
cafePinDto.getLongitude() | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package com.project.yozmcafe.domain.cafe; | ||
|
||
import org.locationtech.jts.geom.Coordinate; | ||
import org.locationtech.jts.geom.GeometryFactory; | ||
import org.locationtech.jts.geom.Point; | ||
|
||
import com.project.yozmcafe.controller.dto.cafe.CafeLocationRequest; | ||
|
||
public class GeometryGenerator { | ||
|
||
private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory(); | ||
/** | ||
* SRID(Spatial Reference Identifier)는 고유한 공간 좌표 식별자입니다. | ||
* <p> | ||
* 그 중, 4326은 WGS84 경위도 좌표계를 의미합니다. GPS 기술에서도 사용되는 좌표계로 범용적으로 가장 널리 사용되는 좌표계입니다. | ||
*/ | ||
private static final int SRID = 4326; | ||
private static final String STRING_POLYGON_FORMAT = "POLYGON((%s))"; | ||
private static final String STRING_GEOMETRY_DELIMITER = " "; | ||
private static final String POINT_DELIMITER = ", "; | ||
|
||
private GeometryGenerator() { | ||
} | ||
|
||
public static Point generatePointWithCoordinate(final double latitude, final double longitude) { | ||
final Point point = GEOMETRY_FACTORY.createPoint(new Coordinate(longitude, latitude)); | ||
point.setSRID(SRID); | ||
return point; | ||
} | ||
|
||
public static String generateStringPolygon(final CafeLocationRequest cafeLocationRequest) { | ||
final double latitude = cafeLocationRequest.latitude(); | ||
final double longitude = cafeLocationRequest.longitude(); | ||
final double latitudeDelta = cafeLocationRequest.latitudeDelta(); | ||
final double longitudeDelta = cafeLocationRequest.longitudeDelta(); | ||
|
||
final String minLatitude = String.valueOf(latitude - latitudeDelta); | ||
final String maxLatitude = String.valueOf(latitude + latitudeDelta); | ||
final String minLongitude = String.valueOf(longitude - longitudeDelta); | ||
final String maxLongitude = String.valueOf(longitude + longitudeDelta); | ||
|
||
final String firstVertex = String.join(STRING_GEOMETRY_DELIMITER, minLatitude, maxLongitude); | ||
final String secondVertex = String.join(STRING_GEOMETRY_DELIMITER, maxLatitude, maxLongitude); | ||
final String thirdVertex = String.join(STRING_GEOMETRY_DELIMITER, maxLatitude, minLongitude); | ||
final String fourthVertex = String.join(STRING_GEOMETRY_DELIMITER, minLatitude, minLongitude); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 원 대신 새로 생긴 사각형 좌표들이군요! 좋아용 |
||
|
||
final String vertexes = String.join(POINT_DELIMITER, firstVertex, secondVertex, thirdVertex, fourthVertex, | ||
firstVertex); | ||
return String.format(STRING_POLYGON_FORMAT, vertexes); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,17 @@ | ||
package com.project.yozmcafe.domain.cafe; | ||
|
||
import java.util.List; | ||
|
||
import jakarta.persistence.CollectionTable; | ||
import jakarta.persistence.ElementCollection; | ||
import jakarta.persistence.Embeddable; | ||
import jakarta.persistence.FetchType; | ||
|
||
import java.util.List; | ||
|
||
@Embeddable | ||
public class Images { | ||
|
||
private static final int REPRESENTATIVE_INDEX = 0; | ||
|
||
@ElementCollection(fetch = FetchType.LAZY) | ||
@ElementCollection | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
@CollectionTable(name = "image") | ||
private List<String> urls; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package com.project.yozmcafe.domain.cafe.coordinate; | ||
|
||
import static jakarta.persistence.GenerationType.IDENTITY; | ||
|
||
import org.locationtech.jts.geom.Point; | ||
|
||
import com.project.yozmcafe.domain.cafe.Cafe; | ||
|
||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.FetchType; | ||
import jakarta.persistence.GeneratedValue; | ||
import jakarta.persistence.Id; | ||
import jakarta.persistence.OneToOne; | ||
|
||
@Entity(name = "cafe_coordinate") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. name 옵션 없애도 될 것 같습니다! |
||
public class CafeCoordinate { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 하나의 엔티티로 만든 이유가 궁금합니다! 제 생각으로는 카페의 전화번호나 주소 등의 추가 정보와 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저도 연어 의견에 동의합니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아 이 부분.. 저도 많이 고민했었는데요. 연어의 말대로 비즈니스적으로 분리가 된다고 생각했습니다. 다른 부분은 모르겠지만, 카페의 주소와는 동일한 변경 주기를 갖고있다는 말에는 백프로 동의합니다. 만약 이 부분이 다른 비즈니스로직에도 사용되어야 하는 경우에는 |
||
|
||
@Id | ||
@GeneratedValue(strategy = IDENTITY) | ||
private Long id; | ||
|
||
private Point coordinate; | ||
|
||
@OneToOne(fetch = FetchType.LAZY) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 연어 의견에 덧붙이자면 @OnetoOne은 양방향일때만 안먹는 거로 아는데 단방향으로 LAZY 처리 해야될 것 같네요 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저는 Cafe <-> CafeCoordinates(필드에 Cafe 갖고있음) 현재 코드는 단방향 매핑관계라 LAZY 잘 먹습니당 ㅎㅎ |
||
private Cafe cafe; | ||
|
||
public CafeCoordinate() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 접근제어자 protected로 바꿔도 좋을 것 같아용 |
||
} | ||
|
||
public CafeCoordinate(final Long id, final Point coordinate, final Cafe cafe) { | ||
this.id = id; | ||
this.coordinate = coordinate; | ||
this.cafe = cafe; | ||
} | ||
|
||
public CafeCoordinate(final Point coordinate, final Cafe cafe) { | ||
this(null, coordinate, cafe); | ||
} | ||
|
||
public double getLatitude() { | ||
return coordinate.getY(); | ||
} | ||
|
||
public double getLongitude() { | ||
return coordinate.getX(); | ||
} | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
|
||
public Point getCoordinate() { | ||
return coordinate; | ||
} | ||
|
||
public Cafe getCafe() { | ||
return cafe; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.project.yozmcafe.domain.cafe.coordinate; | ||
|
||
import java.util.List; | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.data.jpa.repository.Query; | ||
import org.springframework.data.repository.query.Param; | ||
|
||
import com.project.yozmcafe.domain.cafe.coordinate.dto.CafePinDto; | ||
|
||
public interface CafeCoordinateRepository extends JpaRepository<CafeCoordinate, Long> { | ||
|
||
@Query(nativeQuery = true, | ||
value = """ | ||
SELECT c.id, c.name, c.address, ST_X(co.coordinate) AS latitude, ST_Y(co.coordinate) AS longitude | ||
FROM cafe_coordinate co | ||
JOIN cafe AS c | ||
ON co.cafe_id = c.id | ||
WHERE ST_CONTAINS(ST_GeomFromText(:area, 4326), co.coordinate); | ||
""") | ||
List<CafePinDto> findCafePinsFromCoordinate(@Param("area") final String area); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. string으로 범위를 주면 그거에 맞춰서 조회 하나보네요 ㄷㄷ 신기방기 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 정확하게는 |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.project.yozmcafe.domain.cafe.coordinate; | ||
|
||
public class RadiusCalculator { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 정책이 원이 아닌 사각형 내 카페탐색으로 바뀌어서 이 RadiusCalculator클래스와 관련 테스트는 삭제되어도 될 것 같아요! 남겨둔 이유가 있나요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오 지우는거 깜빡했네요! 감사합니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 바로 반영했습니다~ 굿굿 |
||
private static final int METER_PER_DEGREE = 111_000; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이거는 경도위도를 미터로 변환하기 위한 상수인 것 같은데 혹시 왜 111인가요 ? (단순궁금증 수학적인 문제인지 ..?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1도 당 거리가 약 111KM 라고 합니다! 저도 처음 알았어요 ㅋㅋ |
||
|
||
private RadiusCalculator() { | ||
} | ||
|
||
public static double calculate(final double latitude, final double latitudeDelta, final double longitudeDelta) { | ||
double radianLatitude = Math.toRadians(latitude); | ||
|
||
double metersLatitude = latitudeDelta * METER_PER_DEGREE; | ||
double metersLongitude = Math.cos(radianLatitude) * longitudeDelta * METER_PER_DEGREE; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 두 지점의 위도 차이와 경도 차이(longitudeDifference)를 계산 -> 위도 차이를 미터 단위로 변환하기 위해 latitudeDifference에 대해 METER_PER_DEGREE 곱함 -> 경도 차이를 미터 단위로 변환하기 위해 longitudeDifference에 대해 * cos(평균 위도)를 곱한다. 어렵네요 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 위도는 1도 당 거리가 111KM로 동일합니다. 그러나 경도의 경우는 그런데, 한 조각의 거리는 가장 중앙 부분(지구에서 적도해당 )에서 가장 넓고 아래, 위로 갈수록 좁아 지는데요 사실 저도 이해못했습니다. 그렇다길래 아하 그렇구나 하고 했습니다... |
||
|
||
return Math.min(metersLatitude, metersLongitude); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 위도 차이(미터), 경도 차이(미터) 중 작은 것을 리턴하는 메서드인가요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그림에서 가장 오른쪽이 최대 위도, 혹시나 설명이 부족하다면 말씀해주세요 |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.project.yozmcafe.domain.cafe.coordinate.dto; | ||
|
||
public interface CafePinDto { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Projection으로 매핑을 해주는 것이군요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 신기하네요 ... |
||
Long getId(); | ||
|
||
String getName(); | ||
|
||
String getAddress(); | ||
|
||
double getLatitude(); | ||
|
||
double getLongitude(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
implementation 'org.hibernate:hibernate-spatial:6.2.5.Final'
다른 것들과 마찬가지로 이 문법을 사용하면 좋을 것 같아요!